对$函数你已经很熟悉了。它通常返回一个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 链式调用的更多相关文章

  1. JavaScript链式调用

    1.什么是链式调用? 这个很容易理解,例如 $('text').setStyle('color', 'red').show(); 一般的函数调用和链式调用的区别:链式调用完方法后,return thi ...

  2. 关于JavaScript中的setTimeout()链式调用和setInterval()探索

    http://www.cnblogs.com/Wenwang/archive/2012/01/06/2314283.html http://www.cnblogs.com/yangjunhua/arc ...

  3. JavaScript实现链式调用

    学习Jquery的时候,我们通常会看到链式调用的写法 $(window).addEvent('load', function(){ $('test').show().setStyle('color', ...

  4. JavaScript设计模式-8.链式调用

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  5. 《javascript设计模式》笔记之第六章:方法的链式调用

    这一章要实现的就是jQuery的那种链式调用,例子: $(this).setStyle('color', 'green').show(); 一:调用链的结构: 首先我们来看一下最简单的$()函数的实现 ...

  6. JavaScript中的链式调用

    链模式 链模式是一种链式调用的方式,准确来说不属于通常定义的设计模式范畴,但链式调用是一种非常有用的代码构建技巧. 描述 链式调用在JavaScript语言中很常见,如jQuery.Promise等, ...

  7. JavaScript设计模式——方法的链式调用

    方法的链式调用: (function() { //私有类 function _$ (els) { this.elements = []; for(var i = 0, len = els.length ...

  8. javascript学习(10)——[知识储备]链式调用

    上次我们简单的说了下单例的用法,这个也是在我们java中比较常见的设计模式. 今天简单说下链式调用,可能有很多人并没有听过链式调用,但是其实只要我简单的说下的话,你肯定基本上都在用,大家熟知的jQue ...

  9. js原生设计模式——2面向对象编程之js原生的链式调用

    技巧点:对象方法中返回当前对象就可以链式调用了,即方法中写return this; <!DOCTYPE html><html lang="en"><h ...

随机推荐

  1. IDHTTP的基本用法

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 3 ...

  2. JQuery实用技巧

    1.关于页面元素的引用通过jquery的$()引用元素包括通过id.class.元素名以及元素的层级关系及dom或者xpath条件等方法,且返回的对象为jquery对象(集合对象),不能直接调用dom ...

  3. INDEX--从数据存放的角度看索引2

    在上次<INDEX--从数据存放的角度看索引>中,我们说到"唯一非聚集索引"和“非唯一非聚集索引”在存储上有一个明显的差别:唯一非聚集索引的非叶子节点上不会包含RID的 ...

  4. WPF 使用 Direct2D1 画图 绘制基本图形

    本文来告诉大家如何在 Direct2D1 绘制基本图形,包括线段.矩形.椭圆 本文是一个系列 WPF 使用 Direct2D1 画图入门 WPF 使用 Direct2D1 画图 绘制基本图形 本文的组 ...

  5. 【vue】http-server开启本地服务

    在写前端页面中,经常会在浏览器运行HTML页面,从本地文件夹中直接打开的一般都是file协议,当代码中存在http或https的链接时,HTML页面就无法正常打开,为了解决这种情况,需要在在本地开启一 ...

  6. MVC+Nhibernate+spring.net(三)

    当前层次已经分好 分层架构 画的不是太好啊,后面我会上代码,大家先将就着看吧. 现在开始搭建spring 搭建spring首先引用类库文件: spring.AopSpring.Corespring.W ...

  7. 《AngularJS深度剖析与最佳实践》笔记: 第二章 概念介绍

    第二章 概念介绍 2.1 什么是UI? 用户界面包括内容(静态信息+动态信息), 外观, 交互. 在前端技术栈中分别由HTML, CSS和JS负责. 进一步抽象, 分别对应于MVC三个主要部分: Mo ...

  8. [NOI2017]蔬菜(贪心)

    神仙题啊! 早上开了两个多小时,终于肝出来了,真香 我们考虑从第 \(10^5\) 天开始递推,先生成 \(p=10^5\) 的解,然后逐步推出 \(p-1,...,2,1\) 的解. 那怎么推出 \ ...

  9. git add .添加不成功

    情景: 我首先在一个有许多文件的文件夹中  git init  创建一个git管理仓库 之后 git add . 之后 git commit -m "提交" 发现提交不成功,文件没 ...

  10. java实现office文件预览

    不知觉就过了这个久了,继上篇java实现文件上传下载后,今天给大家分享一篇java实现的对office文件预览功能. 相信大家在平常的项目中会遇到需要对文件实现预览功能,这里不用下载节省很多事.大家请 ...