JavaScript中实现DI的原理

在JavaScript中实现DI,看起来难,实际上原理很简单,它的核心技术是Function对象的toString()。我们都知道,对一个函数对象执行toString(),它的返回值是函数的源码,知道了这一点,接下来就简单的:我获取了函数源码,然后我对函数的声明进行解析,伪码如下:

var giveMe = function(config) {
}; var registry = {};
var inject = function(func, thisForFunc) {
// 获取源码
var source = func.toString();
// 用正则表达式解析源码
var matcher = source.match(/..表达式有些复杂,省略../);
// 解析结果是各个参数的名称
var objectIds = ....
// 查阅出相应的对象,放到数组中准备作为参数传过去
var objects = [];
for (var i = 0; i < objectIds.length; ++i)
objects.push(registry[objectIds[i]]);
// 调用这个函数,并且把参数传过去
func.apply(thisForFunc || func, objects)
}; inject(giveMe)

当然,一个实际的DI系统需要考虑的问题比这要多很多,但是这段代码用来表现原理应该足够了。

接下来我们再来看Angular中的DI实现:

在Angular中,所有主要编程元素都需要通过某种方式注册进去,比如myModule.service('serviceName', function().... 这实际上就是把后面这个函数加入到一个容器中,要注意的是:angular全面实现了延迟初始化,也就是说,当这个对象没有被别人需要的时候,它是不会被创建的,这样对于提高性能有一定的帮助,特别是加快了启动速度。

这里一个有趣的问题是:Angular的容器是什么。Angular不存在真正的全局对象,所以你可以放心的在同一个页面中放多个app,而不用担心他们互相干扰,但是容器又需要一个众所周知的地方来存放这些“名字和对象”的注册表(Registry),在Angular中,这个注册表就叫做module,所以,现在你应该知道为什么module的地位很重要了吧?不过一个app中可以存在很多不同名字的module,它们之间存在某些依赖关系,而这体现在module的声明语法中:angular.module('someModule', ['dep1', 'dep2]),这样划分module有利于程序的文件组织。

根据DI的原理,一个自然的推论就是:被注入的对象通常都是单例,因为创建了一个,就可以始终使用它了,不需要多次创建。因此,如果你需要在angular中跨controller共享数据或者通讯,那么你可以创建一个service/value/constant等,然后把它们分别注入到两个controller中,而这两个controller将自然而然的共享同一个对象。

JavaScript中实现DI的原理(二)的更多相关文章

  1. JavaScript中实现DI的原理

    什么是依赖注入 按照上面图的流程中我们可以知道我们需要实现这么几件事: 提供一个服务容器 为目标函数注册需要的依赖 获取目标函数注册的依赖项 通过依赖项来查询对应服务 将获取的依赖项传入目标函数 提供 ...

  2. 前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型

    前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型 前言(题外话): 有人说拖延症是一个绝症,哎呀治不好了.先不说这是一个每个人都多多少少会有的,也不管它究竟对生活有多么大的 ...

  3. 详解javascript中this的工作原理

    在 JavaScript 中 this 常常指向方法调用的对象,但有些时候并不是这样的,本文将详细解读在不同的情况下 this 的指向. 一.指向 window: 在全局中使用 this,它将会指向全 ...

  4. JavaScript中this的工作原理以及注意事项

    在JavaScript中,this 的概念比较复杂.除了在面向对象编程中,this 还是随处可用的.这篇文章介绍了this 的工作原理,它会造成什么样的问题以及this 的相关例子. 要根据this  ...

  5. javaScript中闭包的工作原理

    一.什么是闭包? 官方”的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.相信很少有人能直接看懂这句话,因为他描述的太学术.其实这句话 ...

  6. Javascript中的对象和原型(二)(转载)

    上一篇中提到了JavaScript中对象的创建的一些基本操作,接下来讨论下继续讨论. 一 工厂模式 我们知道,要创建一个对象我们可以用如下代码: var user = new Object(); // ...

  7. javascript中new操作符的原理

    javascript中的new是一个语法糖,对于学过c++,java 和c#等面向对象语言的人来说,以为js里面是有类和对象的区别的,实现上js并没有类,一切皆对象,比java还来的彻底 new的过程 ...

  8. 【干货理解】理解javascript中实现MVC的原理

    理解javascript中的MVC MVC模式是软件工程中一种软件架构模式,一般把软件模式分为三部分,模型(Model)+视图(View)+控制器(Controller); 模型:模型用于封装与应用程 ...

  9. JavaScript 中this的实现原理

    学懂 JavaScript 言语,一个标志就是了解下面两种写法,或许有不一样的成果. <blockquote "=""> var obj = { foo: f ...

随机推荐

  1. WeakHashMap源码分析

    WeakHashMap是一种弱引用map,内部的key会存储为弱引用, 当jvm gc的时候,如果这些key没有强引用存在的话,会被gc回收掉, 下一次当我们操作map的时候会把对应的Entry整个删 ...

  2. php post get 繁体、日文、韩文时 自动添加 反斜杠 问题

    做些二次开发项目,数据库.文件编码没法大规模的修改,比如二次开发一个日文系统,编码是JA16SJIS,$_POST或$_GET的信息中如果“申請”,得到的信息就会变成“申\請”,多出一个反斜杠! 先贴 ...

  3. sql查询字段中的值长度最大的记录

    SELECT max(length(字段)) FROM 表名;

  4. js定时器执行

    第一种:问题请求代表执行打印出来的是什么? //定时器执行页面崩溃 var bo = true; setTimeout(function () { console.log("定时器执行&qu ...

  5. C# 父窗体与子窗体之间委托

    先实例化子窗体jobForm,然后让 jobForm.TransfEvent += job_TransfEvent;显示子窗体 if (jobForm.DialogResult != DialogRe ...

  6. 理解ReentrantLock的公平锁和非公平锁

    学习AQS的时候,了解到AQS依赖于内部的FIFO同步队列来完成同步状态的管理,当前线程获取同步状态失败时,同步器会将当前线程以及等待状态等信息构造成一个Node对象并将其加入到同步队列,同时会阻塞当 ...

  7. 使用SubstanceDesign和Unity插件ShaderForge制作风格化火焰

    使用 SubstanceDesign 软件可以制作shader用的特殊图片,原来真有这种软件,一直好奇这种图片怎么做的 https://www.kancloud.cn/hazukiaoi/sd_sf_ ...

  8. 网络安装Ubuntu16.04

    网络安装Ubuntu16.04 搭建PXE服务器 PXE是Pre-boot Execution Environment,预启动执行环境.是通过网络安装任何linux系统最重要的步骤. 首选搭建PXE服 ...

  9. CCF 201412-4 最优灌溉

    问题描述 试题编号: 201412-4 试题名称: 最优灌溉 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 雷雷承包了很多片麦田,为了灌溉这些麦田,雷雷在第一个麦田挖了一口很 ...

  10. 【c++】访问控制

    1.  类内的访问控制 在基类中,public和private具有普通的含义:用户(即基类的对象)可以访问public成员(包括函数.数据),而不能访问private成员.private只能被基类的成 ...