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 相关文章推荐
一个可以随意添加多个序列的tag函数
Jul 21 Javascript
JavaScript给按钮绑定点击事件(onclick)的方法
Apr 07 Javascript
基于jquery实现全屏滚动效果
Nov 26 Javascript
Node.js编写组件的三种实现方式
Feb 25 Javascript
简单理解JavaScript中的封装与继承特性
Mar 19 Javascript
jQuery制作网页版选项卡
Jul 28 Javascript
js 文字超出长度用省略号代替,鼠标悬停并以悬浮框显示实例
Dec 06 Javascript
微信小程序 开发之快递查询功能的实现
Jan 09 Javascript
微信小程序实现单选选项卡切换效果
Jun 19 Javascript
Element Carousel 走马灯的具体实现
Jul 26 Javascript
react+antd 递归实现树状目录操作
Nov 02 Javascript
原生js+canvas实现验证码
Nov 29 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 adodb连接带密码access数据库实例,测试成功
2008/05/14 PHP
php session应用实例 登录验证
2009/03/16 PHP
用php制作简单分页(从数据库读取记录)的方法详解
2013/05/04 PHP
PHP后门隐藏的一些技巧总结
2020/11/04 PHP
PHP高并发和大流量解决方案整理
2021/03/09 PHP
Using the TextRange Object
2006/10/14 Javascript
jquery cookie的用法总结
2013/11/18 Javascript
javascript读取xml实现javascript分页
2013/12/13 Javascript
js获取视频时长代码
2014/04/10 Javascript
搭建pomelo 开发环境
2014/06/24 Javascript
JavaScript的类型、值和变量小结
2015/07/09 Javascript
JavaScript使用FileSystemObject对象写入文本文件内容的方法
2015/08/05 Javascript
微信小程序 教程之wxapp视图容器 scroll-view
2016/10/19 Javascript
Vue.js基础学习之class与样式绑定
2017/03/20 Javascript
整理关于Bootstrap导航的慕课笔记
2017/03/29 Javascript
在create-react-app中使用css modules的示例代码
2018/07/31 Javascript
vue使用微信JS-SDK实现分享功能
2019/08/23 Javascript
[01:00:54]TI4正赛第二日开场
2014/07/20 DOTA
Python实现全局变量的两个解决方法
2014/07/03 Python
python中urllib.unquote乱码的原因与解决方法
2017/04/24 Python
Python基于回溯法子集树模板实现图的遍历功能示例
2017/09/05 Python
Python中将变量按行写入txt文本中的方法
2018/04/03 Python
python学生信息管理系统(初级版)
2018/10/17 Python
Flask框架单例模式实现方法详解
2019/07/31 Python
python智联招聘爬虫并导入到excel代码实例
2019/09/09 Python
基于python的列表list和集合set操作
2019/11/24 Python
利用Vscode进行Python开发环境配置的步骤
2020/06/22 Python
python判断是空的实例分享
2020/07/06 Python
canvas画布实现手写签名效果的示例代码
2019/04/23 HTML / CSS
美国家喻户晓的保健品品牌:Vitamin World(维他命世界)
2016/08/19 全球购物
学习心得体会
2014/01/01 职场文书
家长对孩子评语
2014/01/30 职场文书
道德模范先进事迹
2014/02/14 职场文书
出纳会计岗位职责
2014/03/12 职场文书
2016年党员公开承诺书范文
2016/03/24 职场文书
2019公司借款合同范本2篇!
2019/07/24 职场文书