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最新动画教程+iso光盘下载
Jan 22 Javascript
javascript instanceof 与typeof使用说明
Jan 11 Javascript
JS+CSS实现表格高亮的方法
Aug 05 Javascript
JavaScript编程中window的location与history对象详解
Oct 26 Javascript
JS中使用apply、bind实现为函数或者类传入动态个数的参数
Apr 26 Javascript
分享Bootstrap简单表格、表单、登录页面
Aug 04 Javascript
Vue组件之Tooltip的示例代码
Oct 18 Javascript
element-ui表格列金额显示两位小数的方法
Aug 24 Javascript
javascript实现的时间格式加8小时功能示例
Jun 13 Javascript
bootstrap table实现横向合并与纵向合并
Jul 18 Javascript
详解基于Vue的支持数据双向绑定的select组件
Sep 02 Javascript
vue+element获取el-table某行的下标,根据下标操作数组对象方式
Aug 07 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
星际争霸 Starcraft 编年史
2020/03/14 星际争霸
PHP实现绘制3D扇形统计图及图片缩放实例
2014/10/01 PHP
使用PHP similar text计算两个字符串相似度
2015/11/06 PHP
thinkPHP自定义类实现方法详解
2016/11/30 PHP
PHP之认识(二)关于Traits的用法详解
2019/04/11 PHP
Laravel Eloquent ORM 多条件查询的例子
2019/10/10 PHP
jQuery的Ajax时无响应数据的解决方法
2010/05/25 Javascript
js判断一个元素是否为另一个元素的子元素的代码
2012/03/21 Javascript
Js制作简单弹出层DIV在页面居中 中间显示遮罩的具体方法
2013/08/08 Javascript
javascript实现捕捉键盘上按下的键
2015/05/05 Javascript
jQuery+JSON实现AJAX二级联动实例分析
2015/12/18 Javascript
javascript中arguments,callee,caller详解
2016/03/16 Javascript
js 判断各种数据类型的简单方法(推荐)
2016/08/29 Javascript
JavaScript中日常收集常见的10种错误(推荐)
2017/01/08 Javascript
jquery.onoff实现简单的开关按钮功能(推荐)
2018/05/24 jQuery
JS中min函数实例讲解
2019/02/18 Javascript
js array数组对象操作方法汇总
2019/03/18 Javascript
NodeJS有难度的面试题(能答对几个)
2019/10/09 NodeJs
vuex存取值和映射函数使用说明
2020/07/24 Javascript
JavaScript中的Proxy对象
2020/11/27 Javascript
[01:13:01]2018DOTA2亚洲邀请赛 4.4 淘汰赛 TNC vs VG 第三场
2018/04/05 DOTA
Python之父谈Python的未来形式
2016/07/01 Python
Python实现一个简单的验证码程序
2017/11/03 Python
python Pexpect 实现输密码 scp 拷贝的方法
2019/01/03 Python
python调试神器PySnooper的使用
2019/07/03 Python
Pytorch实现GoogLeNet的方法
2019/08/18 Python
python selenium循环登陆网站的实现
2019/11/04 Python
在TensorFlow中实现矩阵维度扩展
2020/05/22 Python
英国体育器材进口商店:UK Sport Imports
2017/03/14 全球购物
高档奢华时装在线目的地:FORWARD by elyse walker
2017/10/16 全球购物
Koral官方网站:女性时尚运动服
2019/04/10 全球购物
班主任工作经验材料
2014/02/02 职场文书
导游个人求职信
2014/04/25 职场文书
五四青年节优秀演讲稿范文
2014/05/28 职场文书
Python 详解通过Scrapy框架实现爬取CSDN全站热榜标题热词流程
2021/11/11 Python
DSP接收机前端设想
2022/04/05 无线电