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 相关文章推荐
极酷的javascirpt,让你随意编辑任何网页
Feb 25 Javascript
Lazy Load 延迟加载图片的 jQuery 插件
Feb 06 Javascript
IE6下js通过css隐藏select的一个bug
Aug 16 Javascript
Android中资源文件(非代码部分)的使用概览
Dec 18 Javascript
Egret引擎开发指南之发布项目
Sep 03 Javascript
node.js 使用ejs模板引擎时后缀换成.html
Apr 22 Javascript
JS实现横向拉伸动感伸缩菜单效果代码
Sep 04 Javascript
JavaScript实现的伸展收缩型菜单代码
Oct 14 Javascript
JS+HTML5实现上传图片预览效果完整实例【测试可用】
Apr 20 Javascript
Vue iview-admin框架二级菜单改为三级菜单的方法
Jul 03 Javascript
webpack项目使用eslint建立代码规范实现
May 16 Javascript
纯js+css实现在线时钟
Aug 18 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 文件上传类代码
2011/08/06 PHP
Zend的MVC机制使用分析(一)
2013/05/02 PHP
PHP实现的大文件切割与合并功能示例
2018/04/10 PHP
thinkPHP5框架导出Excel文件简单操作示例
2018/08/03 PHP
PHP count()函数讲解
2019/02/03 PHP
基于ThinkPHP5框架使用QueryList爬取并存入mysql数据库操作示例
2019/05/25 PHP
解决laravel中日志权限莫名变成了root的问题
2019/10/17 PHP
枚举JavaScript对象的函数
2006/12/22 Javascript
IE下js调试工具Companion.JS
2010/10/15 Javascript
js jquery验证银行卡号信息正则学习
2013/01/21 Javascript
jquery实现图片翻页效果
2013/12/23 Javascript
jquery实现简单的瀑布流布局
2016/12/11 Javascript
js 性能优化之算法和流程控制
2017/02/15 Javascript
JS表单数据验证的正则表达式(常用)
2017/02/18 Javascript
整理关于Bootstrap列表组的慕课笔记
2017/03/29 Javascript
Vuejs入门教程之Vue生命周期,数据,手动挂载,指令,过滤器
2017/04/19 Javascript
微信小程序 图片宽高自适应详解
2017/05/11 Javascript
[js高手之路]寄生组合式继承的优势详解
2017/08/28 Javascript
vue实现购物车小案例
2019/09/27 Javascript
Python中使用wxPython开发的一个简易笔记本程序实例
2015/02/08 Python
基于python进行桶排序与基数排序的总结
2018/05/29 Python
Python3.7黑帽编程之病毒篇(基础篇)
2020/02/04 Python
python的help函数如何使用
2020/06/11 Python
解决Ubuntu18中的pycharm不能调用tensorflow-gpu的问题
2020/09/17 Python
Python GUI库Tkiner使用方法代码示例
2020/11/27 Python
CSS3制作炫酷带方向感应的鼠标滑过图片3D动画
2016/03/16 HTML / CSS
马来西亚最大的在线隐形眼镜商店:MrLens
2019/03/27 全球购物
英国时尚高尔夫服装购物网站:Trendy Golf
2020/01/10 全球购物
会计师职业生涯规划范文
2014/02/18 职场文书
小学课外阅读总结
2014/07/09 职场文书
人力资源管理毕业求职信
2014/08/05 职场文书
2014年大学生职业规划书:未来不是梦,只要勇敢冲!
2014/09/22 职场文书
毕业生党员个人总结
2015/02/14 职场文书
2015年七一建党节演讲稿
2015/03/19 职场文书
2016年安康杯竞赛活动总结
2016/04/05 职场文书
如何利用python实现列表嵌套字典取值
2022/06/10 Python