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 相关文章推荐
jQuery自定义事件的简单实现代码
Jan 27 Javascript
javascript如何使用bind指定接收者
May 04 Javascript
如何让浏览器支持jquery ajax load 前进、后退功能
Jun 12 Javascript
JS控制网页动态生成任意行列数表格的方法
Mar 09 Javascript
实例解析JS布尔对象的toString()方法和valueOf()方法
Oct 25 Javascript
Javascript 6里的4个新语法
Aug 25 Javascript
js实现文本上下来回滚动
Feb 03 Javascript
Angular 2父子组件数据传递之@Input和@Output详解 (上)
Jul 05 Javascript
Vue2.0基于vue-cli+webpack Vuex的用法(实例讲解)
Sep 15 Javascript
vue的token刷新处理的方法
Jul 17 Javascript
bootstrap table实现合并单元格效果
Dec 24 Javascript
Javascript Worker子线程代码实例
Feb 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
如何用phpmyadmin设置mysql数据库用户的权限
2012/01/09 PHP
图解找出PHP配置文件php.ini的路径的方法
2014/08/20 PHP
js每次Title显示不同的名言
2008/09/25 Javascript
Jquery 自定义动画概述及示例
2013/03/29 Javascript
Javascript中匿名函数的多种调用方式总结
2013/12/06 Javascript
JS实现的表格操作类详解(添加,删除,排序,上移,下移)
2015/12/22 Javascript
举例讲解jQuery中可见性过滤选择器的使用
2016/04/18 Javascript
Node.js与Sails redis组件的使用教程
2017/02/14 Javascript
node.js调用Chrome浏览器打开链接地址的方法
2017/05/17 Javascript
JavaScript基本语法_动力节点Java学院整理
2017/06/26 Javascript
input输入框内容实时监测(附代码)
2017/08/15 Javascript
js实现控制文件拖拽并获取拖拽内容功能
2018/02/17 Javascript
React Native基础入门之初步使用Flexbox布局
2018/07/02 Javascript
使用jQuery如何写一个含验证码的登录界面
2019/05/13 jQuery
js实现简单掷骰子效果
2019/10/24 Javascript
JavaScript交换变量的常用方法小结【4种方法】
2020/05/07 Javascript
Vue-resource安装过程及使用方法解析
2020/07/21 Javascript
简单的Python的curses库使用教程
2015/04/11 Python
Python os模块学习笔记
2015/06/21 Python
使用python采集脚本之家电子书资源并自动下载到本地的实例脚本
2018/10/23 Python
python实现简单的文字识别
2018/11/27 Python
python绘制散点图并标记序号的方法
2018/12/11 Python
Python读取指定日期邮件的实例
2019/02/01 Python
解决Pycharm双击图标启动不了的问题(JetBrains全家桶通用)
2020/08/07 Python
美国最大的香水连锁店官网:Perfumania
2016/08/15 全球购物
英国领先的维生素和补充剂品牌:Higher Nature
2019/08/26 全球购物
大学生村官工作感言
2014/01/10 职场文书
《中彩那天》教学反思
2014/02/22 职场文书
员工生日活动方案
2014/08/24 职场文书
党的群众路线教育实践活动制度建设计划
2014/11/03 职场文书
繁星春水读书笔记
2015/06/30 职场文书
女方家长婚礼致辞
2015/07/27 职场文书
2016教师廉洁从教心得体会
2016/01/13 职场文书
Python代码风格与编程习惯重要吗?
2021/06/03 Python
微软官方消息,在 2023 年 4 月 11 日之后微软将不再为 Office 2013 和 Skype for Business 2015 提供安全更新
2022/04/21 数码科技
mysqldump进行数据备份详解
2022/07/15 MySQL