var injector = { dependencies: {}, register: function(key, value){ this.dependencies[key] = value; return this; }, resolve: function(){ var firstParams, func, deps = [], scope = null, args = []; firstParams = arguments[0]; scope = arguments[1] || {}; //获得依赖参数 for(var i = 0, len = firstParams.length; i < len; i++){ var val = firstParams[i], type = typeof val; if(type === 'string'){ deps.push(val); }else if(type === 'function'){ func = val; } } //通过依赖参数,找到关联值 for(i = 0, len = deps.length; i < len, d = deps[i]; i++){ if(this.dependencies[d]){ args.push(this.dependencies[d]); }else{ throw new Error('Can\'t find ' + d); } } func.apply(scope || {}, args); } };
测试代码,如下:
<!DOCTYPE html> <head> <meta charset="utf-8"/> </head> <body> <script> var injector = { dependencies: {}, register: function(key, value){ this.dependencies[key] = value; return this; }, resolve: function(){ var firstParams, func, deps = [], scope = null, args = []; firstParams = arguments[0]; scope = arguments[1] || {}; //获得依赖参数 for(var i = 0, len = firstParams.length; i < len; i++){ var val = firstParams[i], type = typeof val; if(type === 'string'){ deps.push(val); }else if(type === 'function'){ func = val; } } //通过依赖参数,找到关联值 for(i = 0, len = deps.length; i < len, d = deps[i]; i++){ if(this.dependencies[d]){ args.push(this.dependencies[d]); }else{ throw new Error('Can\'t find ' + d); } } func.apply(scope || {}, args); } }; //测试代码 injector.register('Monkey', function(){ console.log('Monkey'); }).register('Dorie', function(){ console.log('Dorie'); }); injector.resolve(['Monkey','Dorie',function(M, D){ M(); D(); console.log('-.-'); }]); </script> </body> </html>
因为行内注入声明,是通过字符串的形式作为依赖参数,so,压缩也不怕咯。
最后,我们将上面实现的两种方法,整合到一起,就可以为所欲为啦。
那,就合并下吧,如下:
var injector = { dependencies: {}, register: function(key, value){ this.dependencies[key] = value; return this; }, resolve: function(){ var firstParams, func, deps = [], scope = null, args = []; firstParams = arguments[0]; scope = arguments[1] || {}; //判断哪种形式的注入 if(typeof firstParams === 'function'){ func = firstParams; deps = func.toString().match(/^function\s*[^\(]*\(\s*([^\)]*)\)/m)[1].replace(/ /g, '').split(','); }else{ for(var i = 0, len = firstParams.length; i < len; i++){ var val = firstParams[i], type = typeof val; if(type === 'string'){ deps.push(val); }else if(type === 'function'){ func = val; } } } //通过依赖参数,找到关联值 for(i = 0, len = deps.length; i < len, d = deps[i]; i++){ if(this.dependencies[d]){ args.push(this.dependencies[d]); }else{ throw new Error('Can\'t find ' + d); } } func.apply(scope || {}, args); } };
四、花絮—RequireJS之依赖注入
依赖注入并非在AngularJS中有,倘若你使用过RequireJS,那么下面这种形式,不会陌生吧:
require(['Monkey', 'Dorie'], function(M, D){ //TODO });
通过,上面我们一步步的模拟AngularJS依赖注入的实现,想必,看到这,你自己也会豁然开朗,换汤不换药嘛。
模拟实现如下:
var injector = { dependencies: {}, register: function(key, value){ this.dependencies[key] = value; return this; }, resolve: function(deps, func, scope){ var args = []; for(var i = 0, len = deps.length; i < len, d = deps[i]; i++){ if(this.dependencies[d]){ args.push(this.dependencies[d]); }else{ throw new Error('Can\'t resolve ' + d); } } func.apply(scope || {}, args); } };
测试代码如下:
<!DOCTYPE html> <head> <meta charset="utf-8"/> </head> <body> <script> var injector = { dependencies: {}, register: function(key, value){ this.dependencies[key] = value; return this; }, resolve: function(deps, func, scope){ var args = []; for(var i = 0, len = deps.length; i < len, d = deps[i]; i++){ if(this.dependencies[d]){ args.push(this.dependencies[d]); }else{ throw new Error('Can\'t resolve ' + d); } } func.apply(scope || {}, args); } }; //测试代码 injector.register('Monkey', function(){ console.log('Monkey'); }).register('Dorie', function(){ console.log('Dorie'); }); injector.resolve(['Monkey', 'Dorie'], function(M, D){ M(); D(); console.log('-.-'); }); </script> </body> </html>
五、参考