学习AngularJS的原因之一就是觉得他的DI很牛叉,为了更好的学习,在研究源码之前,想自己按照自己的思路先实现个DI,希望这个思路能够对
学习源码有帮助。

 (function(){
var config;
var di={};
//用来缓存已经生成的对象
var beans=new Array();
di.config=function(conf){
this.config=conf;
return di;
}; /*获取一个方法的参数列表,要求所有注入的参数都已$开头
第二个正则表达是后面的 g 很重要,它表示搜索到第一个之后接着往后搜
没有这个g ,就只能match第一个参数。
这里的参数列表指的就是代码中写的参数列表,不是带入参数后的参数类表
比如有一个方法:
function Fn(a,b,c,c1){}
参数列表就是一个有四个字符串组成的数组:["a","b","c","c1"]
因为需要有参数的名字去匹配参数的类型
*/
var getArguments=function(fun){
return fun.toString().match(/\(.*\)/)[0].match(/\$\w+/g);
};
//核心方法
di.getBean=function(beanName){
//查看缓存,有的话直接返回
if(beans[beanName]!=undefined)
return beans[beanName];
var fn=this.config[beanName];
if(fn==undefined) return;
var args=getArguments(fn);
var argss=new Array();
var objstr="";
var index=0;
var obj;
for(var i in args){
argss[i]=(di.getBean(args[i]));
objstr+="argss["+index+"],";
index++;
}
objstr=objstr.substring(0, objstr.length-1);
objstr="obj=new (fn)("+objstr+"); ";
/*整个DI能够实现就靠这个eval方法了,
它接受一个String参数,并把String里面的内容按照Javasript的标准编译并执行
最牛叉的是eval里面的变量也遵循Javascript的函数作用域:也就是变量可以定义在eval外面
*/
/*
当然这里也可以用apply,或者call,不过总有这样那样的问题,可能是自己对这两个方法不够了解吧
先用eval实现了,以后再研究apply 和call
*/
eval(objstr);
beans[beanName]=obj;
return obj;
};
window.di=di;
})(window);

下面是个例子,

 function Person(){
this.name="Mike";
this.address="China"; this.getName=function(){
return this.name;
};
this.getAddress=function(){
return this .address;
};
}
function Service($person){
this.work=function(){
return $person.getName()+" is living in "+$person.getAddress();
};
} function Adaptor($person,$service){
this.alertt=function(){
var k=$service.work();
alert(k);
};
}

有Person,Service,Adaptor三个类,Service类依赖Person来组装语句,Adaptor类依赖Service类来显示,只要有下面的代码就能运行了

var conf={
"$person":Person,
"$adaptor":Adaptor,
"$service":Service
};
di.config(conf).getBean("$adaptor").alertt();

目前这种DI有个缺陷就是没法再组装时决定类的状态。比如一开始new一个Person时想通过构造方法给name赋值,以上的方式是不能直接做不到的。
只能通过一个间接地方式,如下:

function Person(){
this.name="Mike";
this.getName=function(){
return this.name;
};
this.setName=function($name){
this.name=$name.Name;
};
}
function Name(){
this.NAME="Tom";
}
//然后在Service中使用Person前重新给name赋值
function Service($person,$name){
this.work=function(){
$person.setName($name.NAME);
return $person.getName()+" is living in China"; //这里就成了 Tom is living in China
};
}

javascript的DI的更多相关文章

  1. 细数Javascript技术栈中的四种依赖注入

    作为面向对象编程中实现控制反转(Inversion of Control,下文称IoC)最常见的技术手段之一,依赖注入(Dependency Injection,下文称DI)可谓在OOP编程中大行其道 ...

  2. AngularJS中的DI

    AngularJS中的DI一直以为Angular中的DI是很高大上的东西,也自己写过一个DI的demo,知道其中的难点就是最后动态代码的执行:我现在知道了参数的值,也知道了我要执行的方法/创建对象的类 ...

  3. 每个JavaScript开发人员应该知道的33个概念

    每个JavaScript开发人员应该知道的33个概念 介绍 创建此存储库的目的是帮助开发人员在JavaScript中掌握他们的概念.这不是一项要求,而是未来研究的指南.它基于Stephen Curti ...

  4. 30行代码让你理解angular依赖注入:angular 依赖注入原理

    依赖注入(Dependency Injection,简称DI)是像C#,java等典型的面向对象语言框架设计原则控制反转的一种典型的一种实现方式,angular把它引入到js中,介绍angular依赖 ...

  5. angular 依赖注入原理

    依赖注入(Dependency Injection,简称DI)是像C#,java等典型的面向对象语言框架设计原则控制反转的一种典型的一种实现方式,angular把它引入到js中,介绍angular依赖 ...

  6. JavaScript中实现DI的原理(二)

    JavaScript中实现DI的原理 在JavaScript中实现DI,看起来难,实际上原理很简单,它的核心技术是Function对象的toString().我们都知道,对一个函数对象执行toStri ...

  7. 原创:Javascript DI!Angular依赖注入的实现原理

    DI是Angular的特色功能,而在Angular 2.0的计划中,DI将成为一个独立的模块,参见 https://github.com/angular/di.js 这意味着它也有机会被用于nodej ...

  8. JavaScript中实现DI的原理

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

  9. JavaScript实现常用的排序算法

    ▓▓▓▓▓▓ 大致介绍 由于最近要考试复习,所以学习js的时间少了 -_-||,考试完还会继续的努力学习,这次用原生的JavaScript实现以前学习的常用的排序算法,有冒泡排序.快速排序.直接插入排 ...

随机推荐

  1. [原创]java WEB学习笔记41:简单标签之带属性的自定义标签(输出指定文件,计算并输出两个数的最大值 demo)

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  2. Spring Cloud之Hystrix雪崩效应解决方案

    基于Hystris解决雪崩效应: 1.服务降级:    防止用户一直等待,使用降级方式,调用FallBack(返回友好提示,不会去处理请求) 案例: 当前请求人数过多,请稍后重试 2.服务熔断:(和服 ...

  3. linux 新建分区 、格式化 并挂载的命令

    一.新建分区命令为 fdisk /dev/diskname fdisk命令为交互式命令 p:显示当前硬盘上的分区,包括没保存的改动 n:创建新分区 e:表示扩扩展分区 p:表示主分区 d:删除一个分区 ...

  4. linux sed 命

    sed(stream editor):是流编辑器,按行进行操作,对符合模式的行在内存中进行操作,不对原文件进行修改,处理结束后将模式空间打印到屏幕. sed 的模式空间 处理文件流的内存空间叫模式空间 ...

  5. Cocos2dx版本与CocosBuilder版本匹配问题

    我用的是CocosBuilder 2.1版本,将ccbi导入到xcode 5中时提示: WARNING! Incompatible ccbi file version 警告;ccbi版本不兼容. 查看 ...

  6. java:类集操作总结

    java:类集操作总结 1.List接口允许有重复的元素,Set接口中不允许有重复的元素 2.ArrayList,和Vector的区别 3.set依靠equals和hashCode区分 4.TreeS ...

  7. vmware在桥接模式下配置centos7网络

    首先要将Vmware10.0.3设置为桥接模式. CentOS 7.0默认安装好之后是没有自动开启网络连接的! cd  /etc/sysconfig/network-scripts/  #进入网络配置 ...

  8. hadoop_学习_02_Hadoop环境搭建(单机)

    一.环境准备 1.说明 hadoop的下载来源有: 官方版本:http://archive.apache.org/dist/hadoop/ CDH版本:http://archive.cloudera. ...

  9. spring-springMVC-MyBatis整合配置文件

    web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="htt ...

  10. Execution Context(EC) in ECMAScript

    参考资料 执行环境,作用域理解 深入理解JavaScript系列(2):揭秘命名函数表达式 深入理解JavaScript系列(12):变量对象(Variable Object) 深入理解JavaScr ...