Opening
With the advent of Java EE's Spring Framework, the concept of Dependency injection (IoC) was thoroughly rooted, and it revolutionized our coding patterns and thinking. Before the IOC, we needed to create an object in the program that was simple and straightforward, that is, new object in the code, that we were responsible for creating, maintaining, modifying, and deleting, that is, we controlled the entire life cycle of the object until the object was not referenced and recycled. Admittedly, this is fine when the number of objects created or maintained is small, but when you need to create a large order of objects in a large project, it is difficult to rely solely on the programmer to maintain all objects, especially if you want to reuse some objects throughout the lifetime of the program, We need to write ourselves a cache module to cache all objects, which increases the complexity. Of course, the benefits of the IOC are not limited to this, it also reduces the coupling to dependencies, and does not need to be referenced in the code or can be manipulated depending on the parameters.
In JS, we can introduce the dependency
- Using global variable references
- Pass through function arguments where needed
The disadvantage of using global variables is that it pollutes the global namespace, and the reference is passed through a function, and can be implemented in two ways:
- Closure delivery
- The background resolves the dependent objects and passes the arguments through the Function.prototype.call
In Angularjs, dependency injection is implemented through the latter, and the following sections describe the implementation of the IOC module.
Get dependencies
varFn_args =/^function\s*[^\ (]*\ (\s* ([^\)]*) \)/m;varFn_arg_split =/,/; //Get Service NamevarFn_arg =/^\s* (_?) (\s+?) \1\s*$/;varStrip_comments =/((\/\/.*$) | ( \/\*[\s\s]*?\*\/))/mg;var$INJECTORMINERR = Minerr (' $injector ');functionAnonfn (FN) {//for anonymous functions, showing at the very least the function signature can help in //Debugging. varFntext = fn.tostring (). Replace (Strip_comments, "), args=Fntext.match (Fn_args); if(args) {return' Function (' + (args[1 | | "). Replace (/[\s\r\n]+/, ') + ') '; } return' FN ';}functionannotate (FN, STRICTDI, name) {var$inject, Fntext, Argdecl, last; if(typeoffn = = = ' function ') { if(! ($inject =fn. $inject)) {$inject= []; if(fn.length) {if(STRICTDI) {if(!isstring (name) | |!name) {Name= Fn.name | |ANONFN (FN); } Throw$INJECTORMINERR (' Strictdi ', ' {0} is not using explicit annotation and cannot being invoked in strict mode ', name); } Fntext= Fn.tostring (). Replace (Strip_comments, "); Argdecl=Fntext.match (Fn_args); ForEach (argdecl[1].split (Fn_arg_split),function(ARG) {arg.replace (Fn_arg,function(all, underscore, name) {$inject. push (name); }); }); } fn. $inject=$inject; } } Else if(IsArray (FN)) { Last= Fn.length-1; ASSERTARGFN (Fn[last],' FN '); $inject= Fn.slice (0, last); } Else{ASSERTARGFN (FN,' FN ',true); } return$inject;}
Annotate function through the analysis of the incoming parameter, if the pass is a function, then the dependent module as a parameter transfer, at this time can be through the serialization function for regular matching, get the name of the dependent module and stored in the $inject array returned, in addition, An exception is thrown when execution in strict mode is performed by a function-in-pass dependency , and the second dependency is passed through an array, and the last element of the array is a function that needs to use the dependency. The annotate function eventually returns the resolved dependent name.
The creation of the injector
ANGULARJS API also provides the $injector section, through the $injector can use Get,has,instantiate,invoke and the above mentioned annotate method, through the source can be clearer understanding.
Big
Angularjs source analysis of Dependency injection $injector