学习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
};
}

最新文章

  1. 在linux 服务器上用.htaccess文件实现二级域名访问子目录
  2. java中文乱码解决之道(二)-----字符编码详解:基础知识 + ASCII + GB**
  3. linux sysnc
  4. 我的github代码库
  5. centos---无线上网的电脑所安装的虚拟机网络设置
  6. 转!!URL 传+号到后台变空格问题解决方案
  7. uva 562
  8. 表单设置line-height,在ff中的不垂直居中问题???
  9. C++学习50 对字符串流的读写
  10. stl_alloc.h
  11. Performing Post-Build Event之类的编译错误
  12. MTK Android Driver:GPIO
  13. 【操作教程】利用YCSB测试巨杉数据库性能
  14. 【RabbitMQ+Python入门经典】兔子和兔子窝 笔记
  15. Spring ConditionalOnProperty
  16. hdu3374 最大最小表示法 +kmp
  17. Vivado HLS初识---阅读《vivado design suite tutorial-high-level synthesis》(5)
  18. MeasureOverride和ArrangeOverride 练手项目
  19. RestClient POST
  20. 本地schemeApp扩展

热门文章

  1. spring装配机制
  2. RabbitMQ事务确认机制(生产者)
  3. Mybatis异常_01_Invalid bound statement (not found)
  4. FileInputStream 把文件作为字节流进行读操作
  5. Agc017_E Jigsaw
  6. Gym 101142C :CodeCoder vs TopForces(强连通算法)
  7. 2017-2018-1 20179203 《Linux内核原理与分析》第九周作业
  8. bzoj 1312: Hard Life 01分数规划+网络流
  9. 【LeetCode】012. Integer to Roman
  10. 浏览器全屏的JS代码实现