本文实例分析了JavaScript链式调用。分享给你们供你们参考,具体以下:html
对$函数你已经很熟悉了。它一般返回一个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; }, 欢迎加入全栈开发交流划水交流圈:582735936 面向划水1-3年前端人员 帮助突破划水瓶颈,提高思惟能力 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); } 欢迎加入全栈开发交流划水交流圈:582735936 面向划水1-3年前端人员 帮助突破划水瓶颈,提高思惟能力 };
用户能够这样去使用:学习
installHelper(window, '$'); $('example').show();
下面是一个更复杂的例子,它展现了如何把这种功能添加到一个事先定义好的命名对象中:this
// 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类则使用了回调方法:spa
// 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; } }(); 欢迎加入全栈开发交流划水交流圈:582735936 面向划水1-3年前端人员 帮助突破划水瓶颈,提高思惟能力 // 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'.
以上就是本文的所有内容,但愿对你们的学习有所帮助prototype