JavaScript反射与依赖注入实例详解


Posted in Javascript onMay 29, 2018

本文实例讲述了JavaScript反射与依赖注入。分享给大家供大家参考,具体如下:

对于javascript中的反射的理解,一直都是认为,利用数组对回调函数进行保存,之后在适当的时刻利用call或是apply 方法,对回调进行调用即可,一般如下操作:

首先定义两个方法:

var service = function() {
  return { name: 'Service' };
}
var router = function() {
  return { name: 'Router' };
}

我们有另一个函数需要用到这两个模块。

var doSomething = function(other) {
  var s = service();
  var r = router();
};

当然,我们希望能够能够使用依赖注入的方式去做,把该控制权交给计算机去做,而不是人为的去调用如下:

var doSomething = injector.resolve('router,,service', function(a, b, c) {
  expect(a().name).to.be('Router');
  expect(b).to.be('Other');
  expect(c().name).to.be('Service');
});
doSomething("Other");

那么我们可以造出一个反射方法如下:

var injector ={
    dependencies: {},
    register: function(key, value) {
      this.dependencies[key] = value;
    },
    resolve:function(deps, func, scope) {
      var args = [];
      for(var i=0; i<deps.length, d=deps[i]; i++) {
        if(this.dependencies[d]) {
          args.push(this.dependencies[d]);
        } else {
          throw new Error('Can\'t resolve ' + d);
        }
      }
      return function() {
        func.apply(scope || {}, args.concat(Array.prototype.slice.call(arguments, 0)));
      }
    }
};

如上代码,dependencies 用来保存回调函数集合,resolve用来调用。

这也算是一个比较成熟ok的想法。

但是依旧存在几点问题:

1 resolve 在进行调用时,deps参数列表顺序必须保持一致。

2 这一点有点牵强,但是也算。在调用时,需要再一次的输入形参,而不能直接调用。

那么为了解决以上问题,给出以下解决方案:

var injector ={
    dependencies: {},
    register: function(key, value) {
      this.dependencies[key] = value;
    },
    resolve: function() {
      var func, deps, scope, args = [], self = this;
      if(typeof arguments[0] === 'string') {
        func = arguments[1];
        deps = arguments[0].replace(/ /g, '').split(',');
        scope = arguments[2] || {};
      } else {
        func = arguments[0];
        deps = func.toString().match(/^function\s*[^]*\(\s*([^]*\(\s*([^]*)\)/m)[1].replace(/ /g, '').split(',');
        scope = arguments[1] || {};
      }
      return function() {
        var a = Array.prototype.slice.call(arguments, 0);
        for(var i=0; i<deps.length; i++) {
          var d = deps[i];
          args.push(self.dependencies[d] && d != '' ? self.dependencies[d] : a.shift());
        }
        func.apply(scope || {}, args);
      }
    }
};

利用正则对代码进行解析,解析出function 列表参数,再进行一一自动匹配传值,那么即可解决,顺序必须一直问题,当然这也是当然最热mvvm框架AngularJs采取的方式。

调用方式可以如下:

injector.resolve(['service,,router', function(service, router) {
}]);

你可能注意到在第一个参数后面有两个逗号——注意

这不是笔误。空值实际上代表“Other”参数(占位符)。这显示了我们是如何控制参数顺序的。

最后还有一种方式,直接注入scope ,也就是直接注入作用域,那么作用域被注入,也就不存在上述的传参顺序问题

因为不在需要传递参数,直接可以从作用域中访问到。

var injector = {
  dependencies: {},
  register: function(key, value) {
    this.dependencies[key] = value;
  },
  resolve: function(deps, func, scope) {
    var args = [];
    scope = scope || {};
    for(var i=0; i<deps.length, d=deps[i]; i++) {
      if(this.dependencies[d]) {
        scope[d] = this.dependencies[d];
      } else {
        throw new Error('Can\'t resolve ' + d);
      }
    }
    return function() {
      func.apply(scope || {}, Array.prototype.slice.call(arguments, 0));
    }
  }
}
var doSomething = injector.resolve(['service', 'router'], function(other) {
  expect(this.service().name).to.be('Service');
  expect(this.router().name).to.be('Router');
  expect(other).to.be('Other');
});
doSomething("Other");

javascript反射依赖注入新的理解,记录之,谨防忘记.

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
浅析Javascript使用include/require
Nov 13 Javascript
JavaScript作用域链示例分享
May 27 Javascript
node.js中的fs.utimesSync方法使用说明
Dec 15 Javascript
JavaScript中isPrototypeOf函数作用和使用实例
Jun 01 Javascript
JavaScript中的原型prototype属性使用详解
Jun 05 Javascript
基于jquery实现select选择框内容左右移动添加删除代码分享
Aug 25 Javascript
浅析AngularJS Filter用法
Dec 28 Javascript
js判断当前页面用什么浏览器打开的方法
Jan 06 Javascript
原生js实现addClass,removeClass,hasClass方法
Apr 27 Javascript
Chrome不支持showModalDialog模态对话框和无法返回returnValue问题的解决方法
Oct 30 Javascript
详解javascript replace高级用法
Feb 17 Javascript
JS实现移动端双指缩放和旋转方法
Dec 13 Javascript
使用webpack3.0配置webpack-dev-server教程
May 29 #Javascript
vuejs 切换导航条高亮(路由菜单高亮)的方法示例
May 29 #Javascript
微信小程序6位或多位验证码密码输入框功能的实现代码
May 29 #Javascript
Vue 全局loading组件实例详解
May 29 #Javascript
详解vue-cli 本地开发mock数据使用方法
May 29 #Javascript
详解vue-cli项目中怎么使用mock数据
May 29 #Javascript
js统计页面上每个标签的数量实例代码
May 29 #Javascript
You might like
php 将bmp图片转为jpg等其他任意格式的图片
2009/06/21 PHP
CodeIgniter上传图片成功的全部过程分享
2013/08/12 PHP
php防止用户重复提交表单
2015/11/02 PHP
仿迅雷焦点广告效果(JQuery版)
2008/11/19 Javascript
让div层随鼠标移动的实现代码 ie ff
2009/12/18 Javascript
Kibo 用于处理键盘事件的Javascript工具库
2011/10/28 Javascript
jQuery随便控制任意div隐藏的方法
2013/06/28 Javascript
from表单多个按钮提交用onclick跳转不同action
2014/04/24 Javascript
jQuery调取jSon数据并展示的方法
2015/01/29 Javascript
D3.js实现散点图和气泡图的方法详解
2016/09/21 Javascript
jQuery Ajax传值到Servlet出现乱码问题的解决方法
2016/10/09 Javascript
nodejs基础知识
2017/02/03 NodeJs
jQuery插件HighCharts实现2D柱状图、折线图的组合多轴图效果示例【附demo源码下载】
2017/03/09 Javascript
Bootstrap模态框(Modal)实现过渡效果
2017/03/17 Javascript
使用watch监听路由变化和watch监听对象的实例
2018/02/24 Javascript
JQuery判断radio单选框是否选中并获取值的方法
2019/01/17 jQuery
js blob类型url的视频下载问题的解决
2019/11/29 Javascript
angularjs模态框的使用代码实例
2019/12/20 Javascript
jQuery三组基本动画与自定义动画操作实例总结
2020/05/09 jQuery
[52:32]完美世界DOTA2联赛PWL S2 Magma vs LBZS 第三场 11.18
2020/11/18 DOTA
Python写的PHPMyAdmin暴力破解工具代码
2014/08/06 Python
总结python实现父类调用两种方法的不同
2017/01/15 Python
基于python select.select模块通信的实例讲解
2017/09/21 Python
python多进程中的内存复制(实例讲解)
2018/01/05 Python
python实现隐马尔科夫模型HMM
2018/03/25 Python
Python告诉你木马程序的键盘记录原理
2019/02/02 Python
Python获取命令实时输出-原样彩色输出并返回输出结果的示例
2019/07/11 Python
vue路由实现登录拦截
2021/03/24 Vue.js
怎么写有吸引力的自荐信
2013/11/17 职场文书
九年级化学教学反思
2014/01/28 职场文书
行政助理的岗位职责
2014/02/18 职场文书
打架检讨书2000字
2014/02/22 职场文书
学校领导班子对照检查材料
2014/08/28 职场文书
群众路线四风问题整改措施
2014/09/27 职场文书
全国法制宣传日活动总结
2015/05/05 职场文书
Nginx文件已经存在全局反向代理问题排查记录
2022/07/15 Servers