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. Vue与React的异同 -生命周期

    vue的生命周期 创建前 beforeCreate 创建   create 挂载前 beforeMount 挂载 mounted 更新前 beforeUpdate 更新 updated 销毁前 bef ...

  2. java jdk 1.6 下载

    http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-javase6-41940 ...

  3. 【BZOJ4513】[Sdoi2016]储能表 数位DP

    [BZOJ4513][Sdoi2016]储能表 Description 有一个 n 行 m 列的表格,行从 0 到 n−1 编号,列从 0 到 m−1 编号.每个格子都储存着能量.最初,第 i 行第 ...

  4. [LintCode] 二叉树的后序遍历

    The recursive solution is trivial and I omit it here. Iterative Solution using Stack (O(n) time and  ...

  5. maven pom.xml常用标签 Exclusions plugins是什么意思

    Exclusions maven的依赖(dependencies)有传递性,为了解决兼容性问题,就用exclusions来排除造成兼容性问题的依赖. 写法如下: 加入项目A依赖项目B,项目B依赖项目C ...

  6. 使用ServiceStack缓存技术

    ServiceStack 是一个高性能的 .NET Web 服务框架,简化了开发 XML.JSON.JSV 和 WCP SOAP Web 服务.它定义了符合 Martin Fowlers 数据传输对象 ...

  7. String.prototype.charCodeAt()

    w <script> function wf(w) { console.log(w) } var w = 'ABC'.charCodeAt(0); wf(w) var w = '中'.ch ...

  8. wcf 开发 1

    1.创建wcf应用程序 2.生成服务,启动 3.使用工具生成 文件如下: 4.新增加winform程序项目,并添加文件 service1.cs 修改app.config 5.代码调用 private ...

  9. Python获取指定目录下所有子目录、所有文件名

    需求 给出制定目录,通过Python获取指定目录下的所有子目录,所有(子目录下)文件名: 实现 import os def file_name(file_dir): for root, dirs, f ...

  10. Vue(3)- 安装脚手架、过滤器、生命周期的钩子函数、vue-router基本使用

    一.安装脚手架 1.下载node.js,本文下载版本为node-v8.12.0-x64.msi,一键式安装. 2.安装完成后,打开终端,输入node,可进入node环境(两次ctrl+c退出),如下图 ...