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 设计模式 推荐
Oct 28 Javascript
js 绑定带参数的事件以及手动触发事件
Apr 27 Javascript
深入理解JavaScript系列(2) 揭秘命名函数表达式
Jan 15 Javascript
javascript操作excel生成报表示例
May 08 Javascript
javascript实现的淘宝旅行通用日历组件用法实例
Aug 03 Javascript
javascript显示上周、上个月日期的处理方法
Feb 03 Javascript
高效利用Angular中内置服务$http、$location等
Mar 22 Javascript
js编写的treeview使用方法
Nov 11 Javascript
Vue2组件tree实现无限级树形菜单
Mar 29 Javascript
Vue.js实现文章评论和回复评论功能
May 30 Javascript
vue底部加载更多的实例代码
Jun 29 Javascript
Vue框架里使用Swiper的方法示例
Sep 20 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
解决163/sohu/sina不能够收到PHP MAIL函数发出邮件的问题
2009/03/13 PHP
php中的静态变量的基本用法
2014/03/20 PHP
使用Microsoft Ajax Minifier减小JavaScript文件大小的方法
2010/04/01 Javascript
ExtJS 入门
2010/10/29 Javascript
jquery实现仿Flash的横向滑动菜单效果代码
2015/09/17 Javascript
Nodejs爬虫进阶教程之异步并发控制
2016/02/15 NodeJs
全国省市二级联动下拉菜单 js版
2016/05/10 Javascript
浅谈jQuery animate easing的具体使用方法(推荐)
2016/06/17 Javascript
JS触发服务器控件的单击事件(详解)
2016/08/06 Javascript
jquery实现全选、不选、反选的两种方法
2016/09/06 Javascript
浅谈JS的基础类型与引用类型
2016/09/13 Javascript
Angular4如何自定义首屏的加载动画详解
2017/07/26 Javascript
在vue中通过axios异步使用echarts的方法
2018/01/13 Javascript
Angular通过指令动态添加组件问题
2018/07/09 Javascript
Vue框架下引入ActiveX控件的问题解决
2019/03/25 Javascript
layui2.0使用table+laypage实现真分页
2019/07/27 Javascript
jquery获取并修改触发事件的DOM元素示例【基于target 属性】
2019/10/10 jQuery
JavaScript实现HTML导航栏下拉菜单
2020/11/25 Javascript
Python访问MySQL封装的常用类实例
2014/11/11 Python
详解Django中Request对象的相关用法
2015/07/17 Python
详解python开发环境搭建
2016/12/16 Python
在pycharm中设置显示行数的方法
2019/01/16 Python
django页面跳转问题及注意事项
2019/07/18 Python
Django REST framework 单元测试实例解析
2019/11/07 Python
关于PySnooper 永远不要使用print进行调试的问题
2021/03/04 Python
canvas基础之图形验证码的示例
2018/01/02 HTML / CSS
台湾租车首选品牌:IWS艾维士租车
2019/05/03 全球购物
大学生涯自我鉴定
2014/01/16 职场文书
大学四年个人的自我评价
2014/02/26 职场文书
歌唱比赛主持词
2014/03/18 职场文书
保护环境标语
2014/06/09 职场文书
党的群众路线教育实践活动个人对照检查材料(企业)
2014/11/05 职场文书
感恩教育观后感
2015/06/17 职场文书
2015年政治教研组工作总结
2015/07/22 职场文书
高三毕业感言
2015/07/30 职场文书
关于ObjectUtils.isEmpty() 和 null 的区别
2022/02/28 Java/Android