依赖注入起源于实现控制反转的典型框架Spring框架,用来削减计算机程序的耦合问题。简单来说,在定义方法的时候,方法所依赖的对象就被隐性的注入到该方法中,在方法中可以直接使用,而不需要在执行该函数的时候再参数中添加这些依赖对象。

  理解很简单,我们以一个例子说明

var $name = "chua",$age = 26;
function myInfo($name,$age){
  alert($name + ":" + $age );
};

//普通情况下应该执行
myInfo($name,$age);//"chua:26"
//实现依赖注入以后
myInfo();//本人希望打印的结果是"chua:26",但是毫无疑问在没有实现依赖注入之前是不好使的

  首先,需要有一个函数来接管myInfo的函数定义,不然我们没法拿到myInfo的依赖对象名称加以保存。

function injector(fn){
    //处理fn,保存依赖对象
    ...
    return function(){
      fn.apply({},xxx);//xxx是处理过后的参数
    }
}

//myInfo的定义变成
var myInfo = injector(function ($name,$age){
  alert($name + ":" + $age );
});
myInfo();

  injector函数是怎么获取到myInfo的依赖对象$name、$age的?我们可以通过传入参数的函数fn.toString()来看,

//fn.toString()的结果为下面的字符串
"function myInfo($name,$age){
  alert($name + ":" + $age );
}"

  参考angular的处理:从字符串中读取函数myInfo的参数还是能读取。

  STRIP_COMMENTS =/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm,
  FN_ARGS = /^[^\(]*\(\s*([^\)]*)\)/m,
  FN_ARG =/^\s*(\S+?)\s*$/;
  function injector(fn){
    //处理fn,保存依赖对象
    var fnText = fn.toString().replace(STRIP_COMMENTS, '');//"function myInfo($name,$age){ alert($name + ":" + $age ); }"
    var argDecl = fnText.match(FN_ARGS);//["function myInfo($name,$age)", "$name,$age"]
    var args = argDecl[1].split(",");//["$name","$age"]
    for(var i = 0; i < args.length; i++){
      args[i] = args[i].replace(FN_ARG,"$1");
    }
    ... 
return function(){ fn.apply({},xxx);//xxx是处理过后的参数 } }

  但是有这个还不够,我们虽然拿到了要依赖的对象名称,但是我们并没有给这些名称指定对应的对象。所以应当有一个给这些要依赖的对象注册的过程。

  function injector(fn){
    ...
    var args = argDecl[1].split(",");
    for(var i = 0; i < args.length; i++){
      args[i] = injector.cache[args[i].replace(FN_ARG,"$1")];
    }    
    return function(){
      fn.apply({},args);
    }
  }
  injector.cache = {};
  injector.register = function(key,resource){
    injector.cache[key] = resource;
  }
//先注册要依赖的对象 injector.register(
"$name",$name); injector.register("$age",$age);

  这个时候我们可以使用injector来声明函数了

  var myInfo = injector(function($name,$age){
    alert($name + ":" + $age );
  });
//没有任何参数,得到期望的结果 myInfo();//chua:26

  只要是已经注册过的对象就多可以注入到使用injector函数来声明的函数中使用。完整的测试代码如下

我的angularjs源码学习之旅2——依赖注入
<script>
  var $name = "chua",
  $age = 26,
  STRIP_COMMENTS =/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm,
  FN_ARGS = /^[^\(]*\(\s*([^\)]*)\)/m,
  FN_ARG =/^\s*(\S+?)\s*$/;
  function injector(fn){
    //处理fn,保存依赖对象
    var fnText = fn.toString().replace(STRIP_COMMENTS, '');//"function myInfo($name,$age){ alert($name + ":" + $age ); }"
    var argDecl = fnText.match(FN_ARGS);//["function myInfo($name,$age)", "$name,$age"]
    var args = argDecl[1].split(",");//["$name","$age"]
    for(var i = 0; i < args.length; i++){
      args[i] = injector.cache[args[i].replace(FN_ARG,"$1")];
    }
    return function(){
      fn.apply({},args);
    }
  }
  injector.cache = {};
  injector.register = function(key,resource){
    injector.cache[key] = resource;
  }
  //先注册要依赖的对象
  injector.register("$name",$name);
  injector.register("$age",$age);


  //下面这个奇迹出现的时刻
  var myInfo = injector(function($name,$age){
    alert($name + ":" + $age );
  });
  myInfo();//chua:26
</script>
View Code

相关文章:

  • 2021-12-11
  • 2021-12-07
  • 2021-10-06
  • 2021-11-18
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-08-15
  • 2022-12-23
  • 2022-12-23
  • 2021-10-25
  • 2021-05-20
  • 2022-12-23
  • 2021-07-15
相关资源
相似解决方案