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 相关文章推荐
PJ Blog修改-禁止复制的代码和方法
Oct 25 Javascript
js option删除代码集合
Nov 12 Javascript
IE本地存储userdata的一个bug说明
Jul 01 Javascript
jquery中ajax处理跨域的三大方式
Jan 05 Javascript
Javascript获取随机数的实现方法
Jun 22 Javascript
Vue.js组件tabs实现选项卡切换效果
Dec 01 Javascript
Avalonjs 实现简单购物车功能(实例代码)
Feb 07 Javascript
解决在vue+webpack开发中出现两个或多个菜单公用一个组件问题
Nov 28 Javascript
Vue组件Draggable实现拖拽功能
Dec 01 Javascript
每周一练 之 数据结构与算法(Stack)
Apr 16 Javascript
微信小程序实现左侧滑动导航栏
Apr 08 Javascript
jQuery AJAX应用实例总结
May 19 jQuery
使用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
一个简单的自动发送邮件系统(一)
2006/10/09 PHP
ubuntu下编译安装xcache for php5.3 的具体操作步骤
2013/06/18 PHP
PHP检测字符串是否为UTF8编码的常用方法
2014/11/21 PHP
php递归法读取目录及文件的方法
2015/01/30 PHP
PHP数组实例详解
2016/06/26 PHP
PHP运用foreach神奇的转换数组(实例讲解)
2018/02/01 PHP
Ajax::prototype 源码解读
2007/01/22 Javascript
[原创]提供复制本站内容时出现,该文章转自脚本之家等字样的js代码
2007/03/27 Javascript
JS操作JSON要领详细总结
2013/08/25 Javascript
javascript获得网页窗口实际大小的示例代码
2013/09/21 Javascript
JavaScript知识点总结(六)之JavaScript判断变量数据类型
2016/05/31 Javascript
JS使用单链表统计英语单词出现次数
2016/06/16 Javascript
轻松实现js选项卡切换效果
2016/09/24 Javascript
npm国内镜像 安装失败的几种解决方案
2017/06/04 Javascript
python实现文件分组复制到不同目录的例子
2014/06/04 Python
python使用wmi模块获取windows下硬盘信息的方法
2015/05/15 Python
对numpy中array和asarray的区别详解
2018/04/17 Python
python3正则提取字符串里的中文实例
2019/01/31 Python
Python3环境安装Scrapy爬虫框架过程及常见错误
2019/07/12 Python
python实现把两个二维array叠加成三维array示例
2019/11/29 Python
Pytorch之contiguous的用法
2019/12/31 Python
python字符串,元组,列表,字典互转代码实例详解
2020/02/14 Python
Python爬虫与反爬虫大战
2020/07/30 Python
viagogo法国票务平台:演唱会、体育比赛、戏剧门票
2017/03/27 全球购物
意大利包包和行李箱销售网站:Bagaglio.it
2021/03/02 全球购物
2019年c语言经典面试题目
2016/08/17 面试题
机械设计及其自动化求职推荐信
2014/02/17 职场文书
实习指导老师评语
2014/04/26 职场文书
给学校建议书范文
2014/05/13 职场文书
父亲节寄语大全
2015/02/27 职场文书
党委工作总结2015
2015/04/27 职场文书
小学德育工作总结2015
2015/05/12 职场文书
赢在执行观后感
2015/06/16 职场文书
建国70周年的心得体会(2篇)
2019/09/20 职场文书
如何更改Win11声音输出设备?Win11声音输出设备四种更改方法
2022/04/08 数码科技
CSS的calc函数用法小结
2022/06/25 HTML / CSS