专栏首页IMWeb前端团队js依赖注入初探

js依赖注入初探

本文作者:IMWeb coolriver 原文出处:IMWeb社区 未经同意,禁止转载

前言:一个题目

之前在codewars上做在线题目时遇到这样一个问题:实现一个依赖注入的“注射器”。当时对依赖注入这一概念还不是很理解,只是根据题目的要求初步认识了依赖注入。题目的要求如下:

/**
 * Constructor DependencyInjector
 * @param {Object} - object with dependencies
 */
var DI = function (dependency) {
  this.dependency = dependency;
};

// Should return new function with resolved dependencies
DI.prototype.inject = function (func) {
  // Your code goes here
}

题目先简单地创建了一个依赖注入器的构造函数,题目挑战的方法是在inject函数中编写代码,实现依赖注入。评价挑战成功与否的测试如下:

// 要注入的依赖
var deps = {
  'dep1': function () {return 'this is dep1';},
  'dep2': function () {return 'this is dep2';},
  'dep3': function () {return 'this is dep3';},
  'dep4': function () {return 'this is dep4';}
};

// 新建一个“注射器”
var di = new DI(deps);

// 注射
var myFunc = di.inject(function (dep3, dep1, dep2) {
  return [dep1(), dep2(), dep3()].join(' -> ');
});

// 测试
Test.assertEquals(myFunc(), 'this is dep1 -> this is dep2 -> this is dep3');

先来看一下我之前实现的方案:

/**
 * Constructor DependencyInjector
 * @param {Object} - object with dependencies
 */
var DI = function (dependency) {
  this.dependency = dependency;
};

// Should return new function with resolved dependencies
DI.prototype.inject = function (func) {
  // Your code goes here
  var dependency = this.dependency;

  //返回的函数
  return function(){
    var funArr = [],
        newParm = [];

    // 解析函数参数
    var parmsArr = func.toString().replace(/^function(?:\s|\r|\n)*\(([^\)]*)\)(?:.|\r|\n)*\{(?:.|\r|\n)*\}$/,"$1").split(/\s*,\s*/);
    console.log(parmsArr);
    var obj = {};

    //根据参数查找依赖
    for (var key in dependency){
      if (parmsArr.indexOf(key) >= 0){
        obj[key] = dependency[key];
        newParm.push(key);
      }
    }

    // 待注入的依赖函数定义
    for (var key in obj){
      //console.log("var "+key+" = " + obj[key].toString()+";");
      funArr.push("var "+key+" = " + obj[key].toString()+";");
    }

      // 注入依赖函数定义
    eval("var newfunc="+func.toString().replace(/^(function(?:.|\r|\n)*\{)((?:.|\r|\n)*)(\})$/,"$1"+funArr.join('')+"$2$3"));
    console.log(newfunc.toString());

    // 执行注入依赖后的函数
    return newfunc.apply(obj,newParm);
  }
}

这是较早的时候写的代码,不是很优雅,暴力地将依赖函数的定义注入到函数体中。下面看看codewars上面的大神们写的,根据网站对solution排序的最佳方案:

/**
 * Constructor DependencyInjector
 * @param {Object} - object with dependencies
 */
var DI = function (dependency) {
  this.dependency = dependency;
};

// Should return new function with resolved dependencies
DI.prototype.inject = function (func) {

  var deps = /^[^(]+\(([^)]+)/.exec(func.toString());

 //  构建参数绑定数组
  deps = deps ? deps[1]
    .split(/\s?,\s?/)
    .map(function (dep) {
      return this.dependency[dep];
    }.bind(this)) : [];

  // 通过apply将依赖参数传入函数
  return function () {
    return func.apply(this, deps);
  };

}

看完上面的方案才发现我之前的方案是多么麻烦。。。

依赖注入是什么?

在解决上面是上的问题后,回过头来想:依赖注入是啥?其实通过题目的描述以及测试代码容易理解到,依赖注入可以动态地为函数添加依赖。依赖注入在强类型语言中,如JAVA,比较常见,是一种解藕的方式。 对于如果解释和理解依赖注入,在看了一些“百科”和代码后仍然不是很清晰。后来找到了stackoverflow上的一个问题:如何向一个5岁的小孩解释依赖注入。被认同得最多的答案原文如下:

When you go and get things out of the refrigerator for yourself, you can cause problems. You might leave the door open, you might get something Mommy or Daddy doesn't want you to have. You might even be looking for something we don't even have or which has expired. What you should be doing is stating a need, "I need something to drink with lunch," and then we will make sure you have something when you sit down to eat.

基本的意思是:熊孩子不会自己弄吃的,或者吃到不该吃的,比如这样:

熊孩子只需要告诉家长“我饿了,要吃东西”,家长知道了就给熊孩子准备适合他吃的:

在js中依赖注入的概念不像java中被经常提到,主要原因是在js中很容易就实现了这种动态依赖。最简单的例子:bind函数。js可以通过bind,apply,call等函数可以很方便地控制函数的参数和this变量,所以简单地依赖注入在很多情况下已经被不知不觉地使用。在AMD的模块定义中,其方式也是一种依赖注入。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • js依赖注入初探

    之前在codewars上做在线题目时遇到这样一个问题:实现一个依赖注入的“注射器”。当时对依赖注入这一概念还不是很理解,只是根据题目的要求初步认识了依赖注入。题...

    IMWeb前端团队
  • 用Flux实现TodoMVC

    本文通过实现一个 TodoMVC 应用来说明一个 Flux 应用的结构是怎样的。本文会告诉你如何一步一步地实现这个应用,完整的源代码可以从 Github 下载。...

    IMWeb前端团队
  • 用Flux实现TodoMVC

    本文通过实现一个 TodoMVC 应用来说明一个 Flux 应用的结构是怎样的。本文会告诉你如何一步一步地实现这个应用,完整的源代码可以从 Github 下载。

    IMWeb前端团队
  • js依赖注入初探

    之前在codewars上做在线题目时遇到这样一个问题:实现一个依赖注入的“注射器”。当时对依赖注入这一概念还不是很理解,只是根据题目的要求初步认识了依赖注入。题...

    IMWeb前端团队
  • 搭建直播平台时必须具备的软实力

    直播行业的火速发展带动了一系列产业的发展,而目前直播已经成为CDN服务商的主战场,很多想要搭建直播平台的投资开发商对于CDN在直播过程中所支持的服务并不太了解,...

    用户4372465
  • 第八节dom以及dom库的封装

    河湾欢儿
  • 案例 | 从微信群接单到小程序经营,这个农场短期发展4000+客户!

    月斧山是一座位于重庆市大足宝兴镇的家庭农场,以不打农药和激素的当季蔬菜、小部分水果、酉阳基地粮食喂养(散养)的土鸡鸭及其蛋类为主要销售产品。

    微盛企微管家
  • Nature 神经科学 | 科学家首次发现使用动态贝叶斯推理的脑区

    想象一下,房间里灯关着,黑漆漆的,你刚睡醒,想出门去。你张着双臂摸索着朝门走去,这时你会凭记忆来预测自己离门的距离,并以此决定自己脚下的步子。假如你不小心碰到了...

    新智元
  • 由javascript中"匿名函数调用写法"引出的一些东东

    匿名函数自动调用的三种写法如下: var f1 = function(){alert("f1");}(); (function(){alert("f2");...

    菩提树下的杨过
  • [PHP] 自定义错误处理

    陶士涵

扫码关注云+社区

领取腾讯云代金券