视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
JavaScript趣题:依赖注入
2020-11-27 20:25:13 责编:小采
文档


你想必听说过依赖注入(DI)模式吧?

无论是后端火的一塌糊涂的Spring框架,还是前端潮流angular.js,处处可见依赖注入的身影。

它这个名词有些晦涩,但核心的思想却很简单。

用一句俗话说就是,“要风得风,要雨得雨”,或者说是“饭来张口,衣来伸手”。

你听了我这么一解释,大概还有些迷糊,我就先上一个例子。

下面是一些模块,他们也被称为“依赖”,被存储在一个hash对象中:

var deps = {
 'firstDependency': function () {return 'this is firstDependency';},
 'secondDepency': function () {return 'this is secondDepency';},
};

下面则是一个依赖注入的管理器,到时候是要new出来的:

var DI = function (dependency) {
 this.dependency = dependency;
};

在new的时候,就把deps当参数传进去了。

好,现在问题的关键来了,我们要编写的东西:

DI.prototype.inject = function (func) {......};

这个inject注入方法绑定在DI的原型上,接收一个函数作为参数。

那它该怎么使用呢?

	var di = new DI(deps);

	var myDependentFunc = di.inject(function (secondDepency, firstDependency) {
	 firstDependency();
	 secondDepency();
	});

	myDependentFunc();


大家先观察一下这个inject传入的匿名函数,它代表需求,是我们需要注入的地方。

先看看它的形参,

secondDepency, firstDependency

这里有两个参数,即代表两个需求,到时候,我们要分析这两个参数,查找相关模块。

好,回到inject函数的编写问题上来,第一步该怎么做?

先获取inject传进来函数的toString()形式:

	
	//第一步
	DI.prototype.inject = function (func) {
	func.toString();
	};


接着,分析这个字符串,找出所有的形参:

	
	//第二步
	DI.prototype.inject = function (func) {
	var args = findArgs(func.toString());
	};

findArgs方法该怎么编写?使用正则或者字符串分割截取都可以,这里我用的后者。

String.prototype.trim=function(){
  return this.replace(/(^\s*)|(\s*$)/g, "");
};

var findArgs = function(funcStr){
 var bracket1 = funcStr.indexOf("(");
 var bracket2 = funcStr.indexOf(")");
 var argsStr = funcStr.slice(bracket1+1,bracket2);
 var args = argsStr.split(",");
 return args.map(function(e){
 return e.trim();
 });
};

找出所有的形参后,第三步,从模块hash表中,找出对应的模块函数,存放进实参列表中。

realArgs指代实参列表:

	
	//第三步
	DI.prototype.inject = function (func) {
	var args = findArgs(func.toString());
	var realArgs = [];
	for(var i=0;i<args.length;i++){
	var dep = this.dependency[args[i]];
	if(dep){
	realArgs.push(dep);
	}
	}
	//......
	};


最后一步才是注入,inject返回一个匿名函数,匿名函数执行的时候,通过闭包,获取实参列表,注入到func中。

DI.prototype.inject = function (func) {
 var args = findArgs(func.toString());
 var realArgs = [];
 for(var i=0;i<args.length;i++){
 var dep = this.dependency[args[i]];
 if(dep){
 realArgs.push(dep);
 }
 }
 return function(){
 return func.apply(null,realArgs);
 };
}

这样,一个简单版的注入函数就完工了。

下载本文
显示全文
专题