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 相关文章推荐
非常有用的40款jQuery 插件推荐(系列二)
Dec 25 Javascript
父元素与子iframe相互获取变量和元素对象的具体实现
Oct 15 Javascript
输入框过滤非数字的js代码
Sep 18 Javascript
jquery中checkbox全选失效的解决方法
Dec 26 Javascript
javascript实现下雪效果【实例代码】
May 03 Javascript
ES6中箭头函数的定义与调用方式详解
Jun 02 Javascript
Angular排序实例详解
Jun 28 Javascript
jQuery选择器中的特殊符号处理方法
Sep 08 jQuery
详解微信JS-SDK选择图片遇到的坑
Aug 15 Javascript
react+ant design实现Table的增、删、改的示例代码
Dec 27 Javascript
JAVA面试题 static关键字详解
Jul 16 Javascript
微信小程序实现音频文件播放进度的实例代码
Mar 02 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生成自己的LOG文件
2006/10/09 PHP
如何在PHP中使用Oracle数据库(5)
2006/10/09 PHP
关于ob_get_contents(),ob_end_clean(),ob_start(),的具体用法详解
2013/06/24 PHP
修改apache配置文件去除thinkphp url中的index.php
2014/01/17 PHP
curl不使用文件存取cookie php使用curl获取cookie示例
2014/01/26 PHP
php二维码生成
2015/10/19 PHP
PHP统计目录中文件以及目录中目录大小的方法
2016/01/09 PHP
thinkPHP5实现数据库添加内容的方法
2017/10/25 PHP
如何实现浏览器上的右键菜单
2006/07/10 Javascript
javascript 对象定义方法 简单易学
2009/03/22 Javascript
jQuery学习笔记[1] jQuery中的DOM操作
2010/12/03 Javascript
屏蔽网页右键复制和ctrl+c复制的js代码
2013/01/04 Javascript
js自动生成对象的属性示例代码
2013/10/28 Javascript
Javascript操作URL函数修改版
2013/11/07 Javascript
纯JS实现动态时间显示代码
2014/02/08 Javascript
基于jQuery实现下拉框
2014/11/24 Javascript
jQuery实现延迟跳转的方法
2015/06/05 Javascript
js仿3366小游戏选字游戏
2016/04/14 Javascript
HTML的select控件美化
2017/03/27 Javascript
详解给Vue2路由导航钩子和axios拦截器做个封装
2018/04/10 Javascript
[47:04]EG vs RNG 2019国际邀请赛小组赛 BO2 第二场 8.16
2019/08/18 DOTA
利用Python命令行传递实例化对象的方法
2016/11/02 Python
Python实现统计给定字符串中重复模式最高子串功能示例
2018/05/16 Python
对Python Class之间函数的调用关系详解
2019/01/23 Python
python模块导入的方法
2019/10/24 Python
Django mysqlclient安装和使用详解
2020/09/17 Python
Bobbi Brown芭比波朗美国官网:化妆师专业彩妆保养品品牌
2016/08/18 全球购物
苏宁红孩子母婴商城:redbaby
2017/02/12 全球购物
德国购买健身器材:AsVIVA
2017/08/09 全球购物
新加坡最早生产电动滑板车的制造商之一:FunsToTheFore
2020/09/08 全球购物
介绍一下SQL中union,intersect和minus
2012/04/05 面试题
学校岗位设置方案
2014/01/16 职场文书
关于感谢信的范文
2015/01/23 职场文书
幼儿教师师德师风自我评价
2015/03/05 职场文书
my.ini优化mysql数据库性能的十个参数(推荐)
2021/05/26 MySQL
浅谈mysql返回Boolean类型的几种情况
2021/06/04 MySQL