JavaScript链式调用实例浅析


Posted in Javascript onDecember 19, 2018

本文实例分析了JavaScript链式调用。分享给大家供大家参考,具体如下:

$函数你已经很熟悉了。它通常返回一个html元素或一个html元素的集合,如下:

function$(){
  var elements = [];
  for(vari=0,len=arguments.length;i<len;++i){
     var element = arguments[i];
     if(typeof element ===”string”){
       element = document.getElementById(element);
     }
     if(arguments.length==1){
        return element;
      }
      elements.push(element);
  }
   return elements;
}

但是,如果把这个函数改造为一个构造器,把那些元素作为数组保存在一个实例属性中,并让所有定义在构造器函数的prototype属性所指对象中的方法都返回用以调用方法的那个实例的引用,那么它就具有了链式调用的能力。我首先需要把这个$函数改为一个工厂方法,它负责创建支持链式调用的对象。这个函数应该能接受元素数组形式的参数,以便我们能够使用与原来一样的公用接口。

(function(){
  //use private class
   function _$(els){
    this.elements = [];
     for(vari=0,len=els.length;i<len;i++){
      var element = els[i];
       if(typeof element ===”string”){
        element = document.getElementById(element);
       }
       this.elements.push(element)
     }
   }
    //The public interface remains the same.
    window.$ = function(){
       return new _$(arguments);
    }
})();

由于所有对象都会继承其原型对象的属性和方法,所以我们可以让定义在原型对象中的那几个方法都返回用以调用方法的实例对象的引用,这样就可以对那些方法进行链式调用。想好这一点,我们现在就动手在_$这个私用构造函数的prototype对象中添加方法,以便实现链式调用

(function(){
  //use private class
  function _$(els){
    //..省略之前上面的代码
  }
  _$.prototype = {
    each:function(fn){
      for(var i=0,len=this.elements.length;i<len;i++){
        fn.call(this,this.elements[i]);
      }
      return this;
    },
    show:function(prop,val){
      var that = this;
      this.each(function(el){
        that.setStyle("display”,”block");
      });
      return this;
    },
    addEvent:function(type,fn){
      var add = function(el){
        if(window.addEventListener){
         el.addEventListener(type,fn,false);
        }else if(window.attachEvent){
         el.attachEvent("on"+type,fn);
        }
      };
      this.each(function(el){
        add(el);
      });
      return this;
    }
  };
  //The public interface remains the same.
  window.$ = function(){
    return new _$(arguments);
  }
})();

但是如果某个库或者框架已经定义了一个$函数,那么我们的这个库会将其改写,有个简单的办法是在源码中为$函数另去一个名字。但是如果你是从一个现有的库获得的源码,那么每次代码库获取更新的版本后 你都得重新改名字,因此这个方案并不是很好。好的解决办法就是像下面一样添加一个安装器:

window.installHelper = function(scope, interface) {
  scope[interface] = function() {
   return new _$(arguments);
  }
 };

用户可以这样去使用:

installHelper(window, '$');
$('example').show();

下面是一个更复杂的例子,它展示了如何把这种功能添加到一个事先定义好的命名对象中:

// Define a namespace without overwriting it if it already exists.
window.com = window.com || {};
com.example = com.example || {};
com.example.util = com.example.util || {};
installHelper(com.example.util, 'get');
(function() {
 var get = com.example.util.get;
 get('example').addEvent('click', function(e) {
  get(this).addClass('hello');
 });
})();

有时候把方法连起来并不是一个好主意。链式调用很适合于赋值器方法,但对于取值器的方法,你可能会希望他们返回你要的数据而不是返回this。不过,如果你把链式调用作为首要目标,希望所有方法的使用方式保持一致的话,那么变通的方法还是有的:你可以利用回调技术来返回所要的数据下面有两个例子:其中API类使用了普通的取值器(它中断了调用链),而API2类则使用了回调方法:

// Accessor without function callbacks: returning requested data in accessors.
window.API = window.API || {};
API.prototype = function() {
 var name = 'Hello world';
 // Privileged mutator method.
 setName: function(newName) {
  name = newName;
  return this;
 },
 // Privileged accessor method.
 getName: function() {
  return name;
 }
}();
// Implementation code.
var o = new API;
console.log(o.getName()); // Displays 'Hello world'.
console.log(o.setName('Meow').getName()); // Displays 'Meow'.
// Accessor with function callbacks.
window.API2 = window.API2 || {};
API2.prototype = function() {
 var name = 'Hello world';
 // Privileged mutator method.
 setName: function(newName) {
  name = newName;
  return this;
 },
 // Privileged accessor method.
 //通过把函数作为参数传入
 getName: function(callback) {
  callback.call(this, name);
  return this;
 }
}();
// Implementation code.
var o2 = new API2;
o2.getName(console.log).setName('Meow').getName(console.log);
// Displays 'Hello world' and then 'Meow'.

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
关于innerHTML后丢失动态绑定的EVENT问题解决方法
May 19 Javascript
Javascript中call的两种用法实例
Dec 13 Javascript
jQuery实现商品活动倒计时
Oct 16 Javascript
bootstrap table小案例
Oct 21 Javascript
微信小程序-图片、录音、音频播放、音乐播放、视频、文件代码实例
Nov 22 Javascript
bootstrap中的 form表单属性role=&quot;form&quot;的作用详解
Jan 20 Javascript
Node.js获取前端ajax提交的request信息
Feb 20 Javascript
移动端Ionic App 资讯上下循环滚动的实现代码(跑马灯效果)
Aug 29 Javascript
详解Vue中使用Echarts的两种方式
Jul 03 Javascript
JavaScript模板引擎应用场景及实现原理详解
Dec 14 Javascript
js禁止查看源文件屏蔽Ctrl+u/s、F12、右键等兼容IE火狐chrome
Oct 01 Javascript
浅谈vue2的$refs在vue3组合式API中的替代方法
Apr 18 Vue.js
浅谈vue后台管理系统权限控制思考与实践
Dec 19 #Javascript
如何为vue的项目添加单元测试
Dec 19 #Javascript
浅谈Angular7 项目开发总结
Dec 19 #Javascript
mockjs+vue页面直接展示数据的方法
Dec 19 #Javascript
vue项目搭建以及全家桶的使用详细教程(小结)
Dec 19 #Javascript
vue使用Google地图的实现示例代码
Dec 19 #Javascript
JS实现获取自定义属性data值的方法示例
Dec 19 #Javascript
You might like
php格式化金额函数分享
2015/02/02 PHP
PHP实现删除字符串中任何字符的函数
2015/08/11 PHP
CodeIgniter配置之config.php用法实例分析
2016/01/19 PHP
PHP文件管理之实现网盘及压缩包的功能操作
2017/09/20 PHP
PHP生成随机字符串实例代码(字母+数字)
2019/09/11 PHP
音乐播放用的的几个函数
2006/09/07 Javascript
prototype 学习笔记整理
2009/07/17 Javascript
常用的Javascript数据验证插件
2015/08/04 Javascript
Bootstrap表单布局
2016/07/19 Javascript
Jquery组件easyUi实现手风琴(折叠面板)示例
2016/08/23 Javascript
Vue-cli proxyTable 解决开发环境的跨域问题详解
2017/05/18 Javascript
详解node字体压缩插件font-spider的用法
2018/09/28 Javascript
微信小程序之裁剪图片成圆形的实现代码
2018/10/11 Javascript
Vue 报错TypeError: this.$set is not a function 的解决方法
2018/12/17 Javascript
解决vue scoped html样式无效的问题
2020/10/24 Javascript
echarts柱状图背景重叠组合而非并列的实现代码
2020/12/10 Javascript
[01:02:25]2014 DOTA2华西杯精英邀请赛 5 24 iG VS DK
2014/05/26 DOTA
Python 流程控制实例代码
2009/09/25 Python
Windows系统下使用flup搭建Nginx和Python环境的方法
2015/12/25 Python
python基于FTP实现文件传输相关功能代码实例
2019/09/28 Python
python 利用jinja2模板生成html代码实例
2019/10/10 Python
python paramiko远程服务器终端操作过程解析
2019/12/14 Python
Python Numpy 控制台完全输出ndarray的实现
2020/02/19 Python
Anaconda的安装及其环境变量的配置详解
2020/04/22 Python
Python ADF 单位根检验 如何查看结果的实现
2020/06/03 Python
django filter过滤器实现显示某个类型指定字段不同值方式
2020/07/16 Python
美国值得信赖的婚恋交友网站:eHarmony
2018/10/04 全球购物
高中毕业生生活的自我评价
2013/12/08 职场文书
优秀实习生感言
2014/03/01 职场文书
校园学雷锋活动月总结
2014/03/09 职场文书
政治学求职信
2014/06/03 职场文书
2014年党风建设工作总结
2014/11/19 职场文书
幼儿园教师师德表现自我评价
2015/03/05 职场文书
Redis三种集群模式详解
2021/10/05 Redis
PyTorch device与cuda.device用法
2022/04/03 Python
Android Gradle 插件自定义Plugin实现注意事项
2022/06/16 Java/Android