Angularjs的IOC Inject分析


     在上一篇《Angularjs開發一些經驗總結》中提到angular開發中的IOC inject優先,所以在這節將引用angularjs的注入代碼來分析angularjs的注入方式。在《再談angularjs DI(Dependency Injection)》中提到angularjs的注入方式分為3中方式,如果你還不清楚的請移步。

  1. 推斷式注入:在angularjs中我們可以在我們需要注入的地方按照名稱注入,這里要求參數名稱必須和注入服務實例名稱相同,一種名稱約定,angularjs會提取參數名稱查找相應DI實例注入;
  2. :標記注入:在angularjs中我們可以利用$inject標注DI注入,這里需要注入服務名稱的順序和構造參數名對應.這里可以解決以上約定的死板性;
  3. 內聯注入:對於directives,factory,filter等特殊指令使用$inject標注注入使用不是那么友好,angularjs特別增加了內聯注入。

    在這里我們先上今天的主角code:

 1 /** 
 2 * @ngdoc overview 
 3 * @name AUTO 
 4 * @description 
 5 * 
 6 * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}. 
 7 */ 
 8 
 9 var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m; 
10 var FN_ARG_SPLIT = /,/; 
11 var FN_ARG = /^\s*(_?)(.+?)\1\s*$/; 
12 var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; 
13 function annotate(fn) { 
14   var $inject, 
15       fnText, 
16       argDecl, 
17       last; 
18 
19   if (typeof fn == 'function') { 
20     if (!($inject = fn.$inject)) { 
21       $inject = []; 
22       fnText = fn.toString().replace(STRIP_COMMENTS, ''); 
23       argDecl = fnText.match(FN_ARGS); 
24       forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){ 
25         arg.replace(FN_ARG, function(all, underscore, name){ 
26           $inject.push(name); 
27         }); 
28       }); 
29       fn.$inject = $inject; 
30     } 
31   } else if (isArray(fn)) { 
32     last = fn.length - 1; 
33     assertArgFn(fn[last], 'fn') 
34     $inject = fn.slice(0, last); 
35   } else { 
36     assertArgFn(fn, 'fn', true); 
37   } 
38   return $inject; 
39 }

 

   在上面code中我們可夠很清晰的看到首先這里會判斷是不是一個'function',如果是的我們這會判斷fn.$inject為空,不為空則返回此注入(標記注入),為空則會根據正則匹配獲取參數列表,注入服務的名字按名注入;相反如果不是'function'而是Array的話獲取前n-1的服務名稱注入,這是內聯注入。

 

  關於angularjs注入就到這里,在最后想說下說這代碼中我們能獲取的兩個javascript技巧:

  1. 對於javascript是運行時解釋的弱類型語言,我們無法利用c#,java類似的反射機制去獲取參數信息,我們只能靠正則從javascript代碼中匹配(從function.toString()).
  2. 正則的強大之處,在javascript中replace函數的強大應用:
    arg.replace(FN_ARG, function(all, underscore, name){ 
    $inject.push(name); 
    }); 

     

        關於這點可以參考《JavaScript 函數replace揭秘》。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM