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 数据类型转换(parseInt,parseFloat)
Jul 20 Javascript
javascript实现简单的贪吃蛇游戏
Mar 31 Javascript
JQuery实现级联下拉框效果实例讲解
Sep 17 Javascript
JS实现上下左右对称的九九乘法表
Feb 22 Javascript
基于JavaScript实现百叶窗动画效果不只单纯flas可以实现
Feb 29 Javascript
ichart.js绘制虚线、平均分虚线效果的实现代码
May 05 Javascript
JavaScript中的Object对象学习教程
May 20 Javascript
BootStrap中的Fontawesome 图标
May 25 Javascript
php简单数据库操作类的封装
Jun 08 Javascript
JS检测window.open打开的窗口是否关闭
Jun 25 Javascript
BACKBONE.JS 简单入门范例
Oct 17 Javascript
JS插入排序简单理解与实现方法分析
Nov 25 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
php 需要掌握的东西 不做浮躁的人
2009/12/28 PHP
php下清空字符串中的HTML标签的代码
2010/09/06 PHP
浅谈web上存漏洞及原理分析、防范方法(文件名检测漏洞)
2013/06/29 PHP
分享8个最佳的代码片段在线测试网站
2013/06/29 PHP
smarty简单分页的实现方法
2014/10/27 PHP
浅析Yii2中GridView常见操作
2016/04/22 PHP
laravel-admin 在列表页添加自定义按钮的例子
2019/09/30 PHP
javascript下利用arguments实现string.format函数
2010/08/24 Javascript
跟我学习javascript的垃圾回收机制与内存管理
2015/11/23 Javascript
javascript动态获取登录时间和在线时长
2016/02/25 Javascript
基于jquery fly插件实现加入购物车抛物线动画效果
2016/04/05 Javascript
jQuery Easyui DataGrid点击某个单元格即进入编辑状态焦点移开后保存数据
2016/08/15 Javascript
express文件上传中间件Multer详解
2016/10/24 Javascript
基于Cookie常用操作以及属性介绍
2017/09/07 Javascript
微信小程序中实现手指缩放图片的示例代码
2018/03/13 Javascript
AngularJS 监听变量变化的实现方法
2018/10/09 Javascript
Angular中innerHTML标签的样式不起作用的原因解析
2019/06/18 Javascript
vue之debounce属性被移除及处理详解
2019/11/13 Javascript
JavaScript回调函数callback用法解析
2020/01/14 Javascript
[01:11:27]2018DOTA2亚洲邀请赛小组赛 A组加赛 Newbee vs Optic
2018/04/03 DOTA
Python实现的一个简单LRU cache
2014/09/26 Python
python实现无证书加密解密实例
2014/10/27 Python
Python中unittest模块做UT(单元测试)使用实例
2015/06/12 Python
Python科学计算之NumPy入门教程
2017/01/15 Python
Python+OpenCV实现将图像转换为二进制格式
2020/01/09 Python
Python中有几个关键字
2020/06/04 Python
html5中canvas学习笔记2-判断浏览器是否支持canvas
2013/01/06 HTML / CSS
有模特经验的简历自我评价
2013/09/19 职场文书
善意的谎言事例
2014/02/15 职场文书
《长江之歌》教学反思
2014/04/17 职场文书
中共广东省委常委会党的群众路线教育实践活动整改方案
2014/09/23 职场文书
消费者理赔投诉书
2015/07/02 职场文书
学校财务管理制度
2015/08/04 职场文书
春节随笔
2015/08/15 职场文书
2016年教师节贺卡寄语
2015/12/04 职场文书
三种方式清除vue路由跳转router-link的历史记录
2022/04/10 Vue.js