本文實例分析了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