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 相关文章推荐
JScript中的undefined和&quot;undefined&quot;的区别
Mar 08 Javascript
js同时按下两个方向键
Dec 01 Javascript
JavaScript实现基于十进制的四舍五入实例
Jul 17 Javascript
让你彻底掌握es6 Promise的八段代码
Jul 26 Javascript
基于ajax和jsonp的原生封装(实例)
Oct 16 Javascript
js时间戳转yyyy-MM-dd HH-mm-ss工具类详解
Apr 30 Javascript
JavaScript交换变量的常用方法小结【4种方法】
May 07 Javascript
Vue $emit()不能触发父组件方法的原因及解决
Jul 28 Javascript
如何在vue-cli中使用css-loader实现css module
Jan 07 Vue.js
javascript实现用户必须勾选协议实例讲解
Mar 24 Javascript
Element-ui Layout布局(Row和Col组件)的实现
Dec 06 Vue.js
Vue自定义铃声提示音组件的实现
Jan 22 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
微信营销平台系统?刮刮乐的开发
2014/06/10 PHP
ThinkPHP框架设计及扩展详解
2014/11/25 PHP
PHP里8个鲜为人知的安全函数分析
2014/12/09 PHP
PHP-FPM之Chroot执行环境详解
2015/08/03 PHP
javascript 火狐(firefox)不显示本地图片问题解决
2008/07/05 Javascript
jquery 可排列的表实现代码
2009/11/13 Javascript
js对table的td进行相同内容合并示例详解
2013/12/27 Javascript
jquery Ajax 实现加载数据前动画效果的示例代码
2014/02/07 Javascript
js调用浏览器打印模块实现点击按钮触发自定义函数
2014/03/21 Javascript
纯javascript制作日历控件
2015/07/17 Javascript
Augularjs-起步详解
2016/07/08 Javascript
jQuery动态生成Bootstrap表格
2016/11/01 Javascript
discuz表情的JS提取方法分析
2017/03/22 Javascript
10道典型的JavaScript面试题
2017/03/22 Javascript
vue.js 获取当前自定义属性值
2017/06/01 Javascript
js实现canvas保存图片为png格式并下载到本地的方法
2017/08/31 Javascript
javascript高级模块化require.js的具体使用方法
2017/10/31 Javascript
nodejs实现获取本地文件夹下图片信息功能示例
2019/06/22 NodeJs
vue实现公共方法抽离
2020/07/31 Javascript
原生js生成图片验证码
2020/10/11 Javascript
Python读写Excel文件方法介绍
2014/11/22 Python
一步步教你用Python实现2048小游戏
2017/01/19 Python
Python实现的读取/更改/写入xml文件操作示例
2018/08/30 Python
python生成n个元素的全组合方法
2018/11/13 Python
Python实现的爬取百度贴吧图片功能完整示例
2019/05/10 Python
在Qt5和PyQt5中设置支持高分辨率屏幕自适应的方法
2019/06/18 Python
python实现连续变量最优分箱详解--CART算法
2019/11/22 Python
基于django2.2连oracle11g解决版本冲突的问题
2020/07/02 Python
Python Matplotlib绘图基础知识代码解析
2020/08/31 Python
python切片作为占位符使用实例讲解
2021/02/17 Python
iframe与window.onload如何使用详解
2020/05/07 HTML / CSS
python re模块和正则表达式
2021/03/24 Python
护士检查书
2014/01/17 职场文书
劳资协议书范本
2014/04/23 职场文书
晋江市人民政府党组群众路线教育实践活动整改方案
2014/10/25 职场文书
培训班开班主持词
2015/07/02 职场文书