首页 > 语言 > JavaScript > 正文

Angular.JS学习之依赖注入$injector详析

2024-05-06 15:08:07
字体:
来源:转载
供稿:网友

前言

在依赖注入(IoC)之前,我们在程序中需要创建一个对象很简单也很直接,就是在代码中new Object即可,有我们自己负责创建、维护、修改和删除,也就是说,我们控制了对象的整个生命周期,直到对象没有被引用,被回收。诚然,当创建或者维护的对象数量较少时,这种做法无可厚非,但是当一个大项目中需要创建大数量级的对象时,仅仅依靠程序员来进行维护所有对象,这是难以做到的,特别是如果想在程序的整个生命周期内复用一些对象,我们需要自己写一个缓存模块对所有对象进行缓存,这加大了复杂度。当然,IoC的好处并不仅限于此,它也降低了对依赖的耦合度,不必在代码中进行引用或者传参即可操作依赖。

在js中,我们可以这样引入依赖

1、使用全局变量引用

2、在需要的地方通过函数参数传递

使用全局变量的坏处自不必说,污染了全局的名字空间,而通过函参传递引用,也可以通过两种方法实现:

1、闭包传递

2、后台解析出依赖对象,并通过Function.prototype.call进行传参

而在AngularJS中,依赖注入是通过后者实现的,接下来的几节将会介绍IoC模块的具体实现。

获取依赖

var FN_ARGS = /^function/s*[^/(]*/(/s*([^/)]*)/)/m;var FN_ARG_SPLIT = /,/; // 获取服务名var FN_ARG = /^/s*(_?)(/S+?)/1/s*$/;var STRIP_COMMENTS = /((////.*$)|(///*[/s/S]*?/*//))/mg;var $injectorMinErr = minErr('$injector');function anonFn(fn) { // For anonymous functions, showing at the very least the function signature can help in // debugging. var fnText = fn.toString().replace(STRIP_COMMENTS, ''),  args = fnText.match(FN_ARGS); if (args) { return 'function(' + (args[1] || '').replace(/[/s/r/n]+/, ' ') + ')'; } return 'fn';}function annotate(fn, strictDi, name) { var $inject,  fnText,  argDecl,  last; if (typeof fn === '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 be 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函数通过对入参进行针对性分析,若传递的是一个函数,则依赖模块作为入参传递,此时可通过序列化函数进行正则匹配,获取依赖模块的名称并存入

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选