首页 > 代码库 > javascript的DI

javascript的DI

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

 1 (function(){ 2     var config; 3     var di={}; 4     //用来缓存已经生成的对象 5     var beans=new Array(); 6     di.config=function(conf){     7         this.config=conf; 8         return di; 9     };10     11     /*获取一个方法的参数列表,要求所有注入的参数都已$开头12       第二个正则表达是后面的 g 很重要,它表示搜索到第一个之后接着往后搜13       没有这个g ,就只能match第一个参数。14       这里的参数列表指的就是代码中写的参数列表,不是带入参数后的参数类表15       比如有一个方法:16       function Fn(a,b,c,c1){}17       参数列表就是一个有四个字符串组成的数组:["a","b","c","c1"]18       因为需要有参数的名字去匹配参数的类型19     */20     var getArguments=function(fun){21         return fun.toString().match(/\(.*\)/)[0].match(/\$\w+/g);22     };23     //核心方法24     di.getBean=function(beanName){25         //查看缓存,有的话直接返回26         if(beans[beanName]!=undefined)27             return beans[beanName];2929         var fn=this.config[beanName];30         if(fn==undefined) return;31         var args=getArguments(fn);32         var argss=new Array();33         var objstr="";34         var index=0;35         var obj;36         for(var i in args){37             argss[i]=(di.getBean(args[i]));38             objstr+="argss["+index+"],";39             index++;40         }41         objstr=objstr.substring(0, objstr.length-1);42         objstr="obj=new (fn)("+objstr+"); ";43         /*整个DI能够实现就靠这个eval方法了,44          它接受一个String参数,并把String里面的内容按照Javasript的标准编译并执行45          最牛叉的是eval里面的变量也遵循Javascript的函数作用域:也就是变量可以定义在eval外面46          */47          /*48          当然这里也可以用apply,或者call,不过总有这样那样的问题,可能是自己对这两个方法不够了解吧49          先用eval实现了,以后再研究apply 和call50          */51         eval(objstr);52         beans[beanName]=obj;53         return obj;54     };55     window.di=di;56 })(window);

下面是个例子,

 1 function Person(){ 2     this.name="Mike"; 3     this.address="China"; 4      5     this.getName=function(){ 6         return this.name; 7     }; 8     this.getAddress=function(){ 9         return this .address;10     };11 }12 function Service($person){13     this.work=function(){14         return $person.getName()+" is living in "+$person.getAddress();15     };16 }17 18 function Adaptor($person,$service){19     this.alertt=function(){20         var k=$service.work();21         alert(k);22     };23 }

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

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

 



目前这种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    };}
View Code

 

javascript的DI