Angular.js

辅助函数

  • lowercase
  • hasOwnProperty
  • uppercase
  • mannualLowercase
  • mannualUppercase
  • isArrayLike
  • forEach
  • reverseParams

核心功能

  • angularInit(element, bootstrap)

    找到带有ng-app的节点,读取module,在该节点上启动bootstrap。

  • bootstrap(element, modules, config)

    先往modules中加入“provide”, “ng”两个module,然后调用createInjector(modules, config.strictDi)创建一个injector,再之后如下:

injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector',
function bootstrapApply(scope, element, compile, injector) {
scope.$apply(function() {
element.data('$injector', injector);
compile(element)(scope);
});
}]
);

其实也就是手动调用了一个$scope的更新过程,所以重点在于createInjector和compile两个函数了。

auto/injector.js

辅助函数

  • extractArgs(fn)

    从javascript函数对象中把参数读出来,这个利用了javascript函数的toString()的方法会返回函数的定义的特点。
  • anonFn(fn)

    为一个函数取一个名字
  • annotate(fn, strictDi, name)

    为一个函数添加一个$inject对象,里面存入函数参数列表(?这个还不太确定)

核心函数

injector的主入口是createInjector(modulesToLoad, strictDi),解析这个函数需要一步一步的来:

首先我们必须对Injector的结构有一个透彻了解,参见函数createInternalInjector(cache, factory)。

  • createInternalInjector(cache, factory)

    返回一个injector对象,其中各个属性如下:

    * get(serviceName, caller)

    试图从cache中取出service对象,否则则调用factory(serviceName, caller)并将结果存入cache.

    * injectionArgs(fn, locals, serviceName)

    fn获取其参数列表,然后按照locals[key], getService(key, serviceName)的优先级获取fn的参数返回。

    * invoke(fn, self, locals, serviceName)

    调用injectionArgs(fn, locals, serviceName)实例化arguments, 然后调用fn函数。

    * instantiate(Type, locals, serviceName)

    第一个Type是构造函数,同样调用injectionArgs(Type, locals, serviceName)实例化arguments,然后调用构造函数获取实例并且返回。

    injector的get方法会总是试图从cache中取出实例,当实例不存在时,调用factory方法处理。invoke和instantiate都是先从函数中获取参数列表,然后用locals和cache来实例化参数,然后调用函数获取结果。

  1. 新建了一个变量providerCache,作为所有provider的cache,同时该cache中预存了$provide对象,里面提供了以下方法:

    • provider(name, provider_)
    • factory(name, factoryFn, enforce)
    • service(name, constructor)
    • value(name, value)
    • decorator(serviceName, decorFn)

    除了最后的decorator,这一系列方法都是在providerCache中存入一个包含$get方法的provider。该方法会在各个模块的configProvider中使用,将provider存在providerCache中去。

  2. 利用刚刚的providerCache建立第一个injector: providerInjector, 其factory方法会报错提示provider不存在。

  3. 用一个空对象建立第二个injector: instanceInjector,不同的是它的factory方法,该方法总是先试图用providerInjector获取其provider,然后调用instanceInjector.invoke(provider.$get, provider, undefined, serviceName)。

  4. 在providerCache中加入$injector的provider,因此可以通过injector获取injector自身。

    总结一下,injector基于某一个cache来进行实例的存取和函数参数的实例化,对于不存在的实例,各个injector处理方法不一样,providerInjector是会报错的,而intanceInjector会调用providerInjector首先获取provider,然后实例化instance,最后存入instanceCache中。

  5. 调用loadModules(modulesToLoad),最后使用instanceInjector来invoke返回的runBlocks。

loadModules的内容相对比较直接,阅读其源代码可知道主要做了以下三件事:

1. 加载该module require的modules

2. runInvokeQueue(module._invokeQueue)

2. runInvokeQueue(module._configBlocks)

3. 返回modules的_runBlocks

	runInvokeQueue方法的代码如下:
function runInvokeQueue(queue) {
var i, ii;
for (i = 0, ii = queue.length; i < ii; i++) {
var invokeArgs = queue[i],
provider = providerInjector.get(invokeArgs[0]); provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
}
}
```

loader.js

可以通过阅读下setupModuleLoader的代码来了解angular的module机制。

首先需要了解函数invokeLater(provider, method, insertMethod, queue)和invokeLaterAndSetModuleName(provider, method),当insertMethod, queue都没有提供的时候,它返回匿名函数,该函数调用时将会在queue中inserMethod进[provider, method, arguments]的一个数组。该数组将会被injector调用。如上一章的code所示,它将会先取出provider,然后调用其method(arguments)。

这里我们看到module.provider的定义是invokeLaterAndSetModuleName('$provide', 'provider')

因此当我们调用angular.module(test).provider()时,它将会在该module的queue里存入相应的数据,之后在angular初始化时,它将会用providerInjector取出$provide服务,然后我们可以调用它里面的各种预存方法,从而将provider预存进providerCache。

AngularJS Source code的更多相关文章

  1. Tips for newbie to read source code

    This post is first posted on my WeChat public account: GeekArtT Reading source code is always one bi ...

  2. 编程等宽字体Source Code Pro(转)

    Source Code Pro - 最佳的免费编程字体之一!来自 Adobe 公司的开源等宽字体下载     每一位程序员都有一套自己喜爱的代码编辑器与编程字体,譬如我们之前就推荐过一款"神 ...

  3. How to build the Robotics Library from source code on Windows

    The Robotics Library is an open source C++ library for robot kinematics, motion planning and control ...

  4. How to build windows azure PowerShell Source Code

    Download any version source code of Windows Azure Powershell from https://github.com/Azure/azure-sdk ...

  5. akka cluster sharding source code 学习 (1/5) 替身模式

    为了使一个项目支持集群,自己学习使用了 akka cluster 并在项目中实施了,从此,生活就变得有些痛苦.再配上 apache 做反向代理和负载均衡,debug 起来不要太酸爽.直到现在,我还对 ...

  6. view class source code with JAD plugin in Eclipse

    The default class viewer doesn't decompile the class file so you cannot open and check the source co ...

  7. Classic Source Code Collected

    收藏一些经典的源码,持续更新!!! 1.深度学习框架(Deep Learning Framework). A:Caffe (Convolutional Architecture for Fast Fe ...

  8. Attach source code to a Netbeans Library Wrapper Module

    http://rubenlaguna.com/wp/2008/02/22/attach-source-code-to-a-netbeans-library-wrapper-module/ Attach ...

  9. convert source code files to pdf format in python

    import os import sys def find_file(root_dir, type): dirs_pool = [root_dir] dest_pool = [] def scan_d ...

随机推荐

  1. 数据库读写分离(aop方式完整实现)

    http://blog.csdn.net/machunlin2010/article/details/46471983

  2. delphi连接sql server数据库,并根据sql语句查询出数据显示--初级

    需要用到四个组件,分别为: 1.ADOConnection1 设置Connectionstring属性(连接串),loginPrompt属性控制是否连接记住了密码: 2.ADOQuery1 设置Con ...

  3. Minecraft Forge编程入门一 “环境搭建”

    什么是Forge Minecraft Forge is a Minecraft application programming interface (API) which allows almost ...

  4. 如果"一切是IO"“一切是file”是成立的,那么上述的想法也一定可以实现吧 awk对apache日志分析 ---

    定时执行 自动化处理 直接入库 再去读取这个file入库: root@VM---ubuntu:/var/log/apache2# awk '{print $1 "\t" $7}' ...

  5. 面向对象 - 1.封装之如何实现属性的隐藏/2.封装的意义/3.封装与扩展性/4.property的使用

    1.封装之如何实现属性的隐藏封装: __x=1 # 把数据属性隐藏 (如何实现隐藏) 类定义阶段 __开头发生了变形 __x --> _A__x特点: 1.在类外部无法直接:obj.__Attr ...

  6. XML 解析之 dom4j 解析器

    dom4j 的使用需要导入 jar 包, 包括: dom4j-1.6.1 和 jaxen-1.1-beta 步骤: 在项目目录下,"Folder" 创建一个 lib 文件夹 复制 ...

  7. shell正则式解析身份证和手机号

    cat test2.html | sed -e 's/\(^\|[^0-9]\)\(13[0-9][0-9]\{8\}\|14[579][0-9]\{8\}\|15[0-3,5-9][0-9]\{8\ ...

  8. IDEA 录制宏+设置快捷键 实现写时编译

    参考: IDEA 录制宏+设置快捷键 实现写时编译:https://blog.csdn.net/wangjie919/article/details/79487981 IDEA 设置运行时不编译项目: ...

  9. 0407-服务注册与发现-Eureka深入理解-元数据、高可用HA

    一.Eureka元数据 参看地址:https://cloud.spring.io/spring-cloud-static/Edgware.SR3/single/spring-cloud.html#_e ...

  10. golang的多协程实践

    go语言以优异的并发特性而闻名,刚好手上有个小项目比较适合. 项目背景: 公司播控平台的数据存储包括MySQL和ElasticSearch(ES)两个部分,编辑.运营的数据首先保存在MySQL中,为了 ...