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. activeMQ安装与测试

    Apache ActiveMQ简介 activeMQ是JMS的一种具体的实现,是最流行的,能力强劲的开源消息总线.activeMQ具有以下优势: 多种语言和协议编写客户端(java.C.C++.AJA ...

  2. 170111、MapperScannerConfigurer处理过程源码分析

    前言 本文将分析mybatis与spring整合的MapperScannerConfigurer的底层原理,之前已经分析过java中实现动态,可以使用jdk自带api和cglib第三方库生成动态代理. ...

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

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

  4. JDK源码分析之concurrent包(四) -- CyclicBarrier与CountDownLatch

    上一篇我们主要通过ExecutorCompletionService与FutureTask类的源码,对Future模型体系的原理做了了解,本篇开始解读concurrent包中的工具类的源码.首先来看两 ...

  5. 网站漏洞扫描工具(appscan,mdcsoft-ips)

    网站漏洞扫描工具:主要应用网站漏洞扫描工具,其原理是通过工具通过对网站的代码阅读,发现其可被利用的漏洞进行告示,通过前人收集的漏洞编成数据库,根据其扫描对比做出. 具体网站扫描工具有:appscan, ...

  6. tcp连接是基于socket通信的吗

    https://zhidao.baidu.com/question/1305788160020716299.html ------ 网络七层协议 五层模型 TCP连接 HTTP连接 socket套接字 ...

  7. 关于增强for循环和普通for循环是否需要判断为null的情况

    1.增强for循环: public static void main(String[] args) { List<Object> list = null; for(Object s : l ...

  8. onchange事件可以使用于: <input>, <select>, 和 <textarea>。

    onchange 事件会在域的内容改变时发生. onchange 事件也可用于单选框与复选框改变后触发的事件.

  9. java中byte[] 和16进制字符串互转

    //将byte[]转换为16进制字符串 public static String byte2hex(byte[] b) { StringBuilder hs = new StringBuilder() ...

  10. Andrew Ng机器学习编程作业:Anomaly Detection and Recommender Systems

    作业文件 machine-learning-ex8 在本次练习,第一节我们将实现异常检测算法,并把它应用到检测网络故障服务器上.在第二部分,我们将使用协同过滤来构建电影推荐系统. 1. 异常检测 在这 ...