• 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 和call
    50          */
    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
  • 相关阅读:
    【前端开发】关于闭包最通俗易懂的解释 for循环,定时器,闭包混合一块的那点事。
    【前端node开发】你需要的Express开发教程
    【前端vue开发】vue开发输入姓名,电话,公司表单提交组件
    【前端vue开发】vue知识点超链接学习笔记
    【前端vue开发】vue子调父 $emit (把子组件的数据传给父组件)
    【前端vue开发】vue项目使用sass less扩展语言所要安装的依赖
    【轨迹动画css】不规则轨迹动画css教程,弹球,客服广告悬浮层都可以用
    【前端vue开发架构】vue开发单页项目架构总结
    3D全景漫游
    一些好的网站
  • 原文地址:https://www.cnblogs.com/formyjava/p/4160484.html
Copyright © 2020-2023  润新知