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 相关文章推荐
JS类定义原型方法的两种实现的区别评论很多
Sep 12 Javascript
动态载入/删除/更新外部 JavaScript/Css 文件的代码
Jul 03 Javascript
解析JavaScript中instanceof对于不同的构造器或许都返回true
Dec 03 Javascript
JavaScript onkeypress事件入门实例(按下或按住一个键盘按键)
Oct 17 Javascript
浅谈jquery选择器 :first与:first-child的区别
Nov 20 Javascript
bootstrap-datetimepicker实现只显示到日期的方法
Nov 25 Javascript
bootstrap网格系统使用方法解析
Jan 13 Javascript
JavaScript基于DOM操作实现简单的数学运算功能示例
Jan 16 Javascript
浅谈键盘上回车按钮的js触发事件
Feb 13 Javascript
JavaScript限制在客户区可见范围的拖拽(解决scrollLeft和scrollTop的问题)(2)
May 17 Javascript
浅谈JavaScript的innerWidth与innerHeight
Oct 12 Javascript
JavaScript canvas实现雨滴特效
Jan 10 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之第二天
2006/10/09 PHP
js和php邮箱地址验证的实现方法
2014/01/09 PHP
CodeIgniter框架中_remap()使用方法2例
2014/03/10 PHP
destoon整合ucenter后注册页面不跳转的解决方法
2014/06/21 PHP
使用YII2框架实现微信公众号中表单提交功能
2017/09/04 PHP
实现laravel 插入操作日志到数据库的方法
2019/10/11 PHP
JavaScript 异步调用框架 (Part 3 - 代码实现)
2009/08/04 Javascript
PHP 与 js的通信(via ajax,json)
2010/11/16 Javascript
JS获取地址栏参数的小例子
2013/08/23 Javascript
指定区域的图片自动按比例缩小的js代码(防止页面被图片撑破)
2014/02/21 Javascript
jQuery实现的导航条切换可显示隐藏
2014/10/22 Javascript
AngularJS实现ajax请求的方法
2016/11/22 Javascript
Javascript之面向对象--封装
2016/12/02 Javascript
node文件上传功能简易实现代码
2017/06/16 Javascript
Less 安装及基本用法
2018/05/05 Javascript
Angularjs实现数组随机排序的方法
2018/10/02 Javascript
使用webpack打包后的vue项目如何正确运行(express)
2018/10/26 Javascript
jQuery实现适用于移动端的跑马灯抽奖特效示例
2019/01/18 jQuery
vue项目使用$router.go(-1)返回时刷新原来的界面操作
2020/07/26 Javascript
[02:16]DOTA2超级联赛专访Burning 逆袭需要抓住机会
2013/06/24 DOTA
Windows下Eclipse+PyDev配置Python+PyQt4开发环境
2016/05/17 Python
使用Selenium破解新浪微博的四宫格验证码
2018/10/19 Python
最新版 Windows10上安装Python 3.8.5的步骤详解
2020/11/28 Python
详解HTML5 Canvas标签及基本使用
2020/01/10 HTML / CSS
Html5 canvas画图白板踩坑
2020/06/01 HTML / CSS
Ralph Lauren法国官网:美国高品味时装品牌
2017/12/08 全球购物
TripAdvisor瑞典:全球领先的旅游网站
2017/12/11 全球购物
写自荐信的七个技巧
2013/10/15 职场文书
本科生求职简历的自我评价
2013/10/21 职场文书
商务英语本科生的自我评价分享
2013/11/15 职场文书
优秀求职自荐信怎样写
2013/12/18 职场文书
自我鉴定怎么写
2014/01/12 职场文书
首席执行官观后感
2015/06/03 职场文书
消夏晚会主持词
2015/06/30 职场文书
微信早安问候语
2015/11/10 职场文书
MYSQL事务的隔离级别与MVCC
2022/05/25 MySQL