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 相关文章推荐
javascript web对话框与弹出窗口
Feb 22 Javascript
Iframe自适应高度绝对好使的代码 兼容IE,遨游,火狐
Jan 27 Javascript
JavaScript高级程序设计阅读笔记(六) ECMAScript中的运算符(二)
Feb 27 Javascript
使用javascript过滤html的字符串(注释标记法)
Jul 08 Javascript
jquery实现多屏多图焦点图切换特效的方法
May 04 Javascript
jQuery 的 ready()的纯js替代方法
Nov 20 Javascript
Angular.js中数组操作的方法教程
Jul 31 Javascript
详解用webpack的CommonsChunkPlugin提取公共代码的3种方式
Nov 09 Javascript
webpack+vue-cil中proxyTable处理跨域的方法
Jul 20 Javascript
JS实现HTML页面中动态显示当前时间完整示例
Jul 30 Javascript
5分钟快速掌握JS中var、let和const的异同
Sep 19 Javascript
在vue使用clipboard.js进行一键复制文本的实现示例
Jan 15 Javascript
浅谈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
判断Keep-Alive模式的HTTP请求的结束的实现代码
2011/08/06 PHP
如何高效率去掉js数组中的重复项
2016/04/12 Javascript
jQuery File Upload文件上传插件使用详解
2016/12/06 Javascript
JS实现的样式切换功能tableCSS实例
2016/12/30 Javascript
js中DOM三级列表(代码分享)
2017/03/20 Javascript
详解win7 cmd执行vue不是内部命令的解决方法
2017/07/27 Javascript
jQuery条件分页 代替离线查询(附代码)
2017/08/17 jQuery
使用JQ完成表格隔行换色的简单实例
2017/08/25 Javascript
ES6中Array.copyWithin()函数的用法实例详解
2017/09/16 Javascript
BootStrap点击保存后实现模态框自动关闭的思路(模态框)
2017/09/26 Javascript
vue实现按需加载组件及异步组件功能
2019/05/27 Javascript
nodejs的安装使用与npm的介绍
2019/09/11 NodeJs
vue 实现websocket发送消息并实时接收消息
2019/12/09 Javascript
[02:26]DOTA2英雄米拉娜基础教程
2013/11/25 DOTA
python判断、获取一张图片主色调的2个实例
2014/04/10 Python
用Python实现通过哈希算法检测图片重复的教程
2015/04/02 Python
使用Python的Zato发送AMQP消息的教程
2015/04/16 Python
Python使用django获取用户IP地址的方法
2015/05/11 Python
Python模糊查询本地文件夹去除文件后缀的实例(7行代码)
2017/11/09 Python
Python基于列表list实现的CRUD操作功能示例
2018/01/05 Python
python绘制多个曲线的折线图
2020/03/23 Python
Python Flask 搭建微信小程序后台详解
2019/05/06 Python
Atom Python 配置Python3 解释器的方法
2019/08/28 Python
python 使用opencv 把视频分割成图片示例
2019/12/12 Python
Python SMTP配置参数并发送邮件
2020/06/16 Python
Python中三维坐标空间绘制的实现
2020/09/22 Python
加拿大著名的奢侈品购物网站:SSENSE(支持中文)
2020/06/25 全球购物
汽车驾驶求职信
2013/10/25 职场文书
销售副总经理岗位职责
2013/12/11 职场文书
信息专业大学生自我评价分享
2014/01/17 职场文书
煤矿安全承诺书
2014/05/22 职场文书
银行金融服务方案
2014/06/11 职场文书
感情真挚的毕业生求职信
2014/07/19 职场文书
2016最新离婚协议书范本及程序
2016/03/18 职场文书
财产分割协议书
2016/03/22 职场文书
python实现自动清理文件夹旧文件
2021/05/10 Python