Self-developed angularjs dependency injection and angularjs dependency Injection
Angular dependency injection makes it easy to use. He appeared to "Reduce the coupling problem of computer programs". With reverence and curiosity, I gently walked into angular source code, let's see how he implements it. I also want to write such a awesome function. Therefore, I wrote one. If there is anything wrong, please criticize and correct it.
In fact, at the beginning, I didn't know how to get started. Some of the source code was indeed obscure and I didn't understand it yet, so I calmed down and thought about it, how is it used, as shown below:
Angular. module (/* omitted */). factory ("xxxService", ['XX', function (xx) {return {// omitted}]). controller ('iicontroller', ['xxxservice', function (xxxService) {// omitted}]);/*... method omitted .. */
Let's look at the usage in the strict mode above. Let's not look at the source code first. How can we achieve service reuse without using the controller? I created a cache to save the service as per my own ideas. The controller only runs once and is not saved to the cache.
With some ideas, I wrote the necessary things first,
(Function (global) {function CreateInjector (cache) {this. cache = cache; // The cache used to save the service} function Angular () {} Angular. module = function () {var moduleObj = {}; return {injector: new CreateInjector (moduleObj), factory: function (name, fn) {}, controller: function (name, fn) {}}; global. angular = Angular;}) (window );
The preceding two constructors are the constructor and the static module of angular (you do not need to create the constructor name directly. method Name ", here is to imitate angular. module () method. Here, the angular module method is short for. It also has dependency injection, but my capabilities are limited. I first studied the injection of controller and service. The above method names are all copied to the source code. I will not explain them here.
Because we are studying dependency injection, the real core code is as follows:
var ARROW_ARG = /^([^\(]+?)=>/;var FN_ARGS = /^[^\(]*\(\s*([^\)]*)\)/m;var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;function isArray(obj){ return Object.prototype.toString.call(obj) === '[object Array]';}function stringifyFn(fn) { return fn.toString();}function extractArgs(fn) { var fnText = stringifyFn(fn).replace(STRIP_COMMENTS, ''), args= fnText.match(ARROW_ARG) || fnText.match(FN_ARGS); return args[1].split(',');}function CreateInjector(cache){ this.cache=cache;}CreateInjector.prototype={ constructor:CreateInjector, invoke:function(fn,self){ var argsName= extractArgs(fn),argsFn=[]; argsName.forEach(function(arg){ argsFn.push(this.cache[arg]); },this); if(isArray(fn)){ return fn[fn.length-1].apply(self,argsFn); }else{ return fn.apply(self,argsFn); } }};
The above regular expression is copied to the Source Code. The Code principle is:
(1) extract the passed function toString (), use regular match to get the passed parameter name, and split the parameter into parameter arrays using split;
(2) loop parameter array: Find the function under this parameter in the cache and push it to a function array;
(3) Use apply to treat the Function Array as a parameter and execute the function;
For the transmitted fn, determine whether it is in the array format or normal. If it is an array, apply the last value, that is, the function. Otherwise, the fn itself is used.
I didn't handle the error above, for example, the injection cannot be found, and so on. If you are interested, add it.
The final code is as follows. You can copy and run the Code:
<!DOCTYPE html>
Thank you!
The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.