您好,登錄后才能下訂單哦!
雖然最近工作中沒有怎么用 zepto ,但是據說 zepto 的源碼比較簡單,而且網上的資料也比較多,所以我就挑了 zepto 下手,希望能為以后閱讀其他框架的源碼打下基礎吧。
本文閱讀的源碼為 zepto1.2.0
閱讀zepto之前需要了解 javascript 原型鏈和閉包的知識,推薦閱讀王福朋的這篇文章:深入理解 Javascript 原型和閉包,寫得很詳細,也非常易于閱讀。
var Zepto = (function () { ...})()window.Zepto = Zeptowindow.$ === undefined && (window.$ = Zepto)
如果在編輯器中將 zepto 的源碼折疊起來,看到的就跟上面的代碼一樣。
zepto 的核心是一個閉包,加載完畢后立即執行。然后暴露給全局變量 zepto
,如果 $
沒有定義,也將 $
賦值為 zepto
。
在這部分中,我們先不關注 zepto 的具體實現,只看核心的結構,因此我將zepto中的邏輯先移除,得出如下的核心結構:
var zepto = {}, $function Z(doms) { var len = doms.length for (var i = 0; i < len; i++) { this[i] = doms[i] } this.length = doms.length}zepto.Z = function(doms) { return new Z(doms)}zepto.init = function(doms) { var doms = ['domObj1','domObj2','domObj3'] return zepto.Z(doms)}$ = function() { return zepto.init()}$.fn = { constructor: zepto.Z, method: function() { return this }}zepto.Z.prototype = Z.prototype = $.fnreturn $
在源碼中,可以看出, $
其實是一個函數,同時在 $
身上又掛了很多屬性和方法(這里體現在 $.fn
身上,其他的會在后續的文章中談到)。
我們在使用 zepto 的時候,會用 $
去獲取 dom
,并且在這些 dom
對象身上都有 zepto 定義的各種各樣的操作方法。
從上面的偽代碼中,可以看到,$
其實調用了 zepto.init()
方法,在 init
方法中,會獲取到 dom
元素集合,然后將集合交由 zepto.Z()
方法處理,而 zepto.Z
方法返回的是函數 Z
的一個實例。
函數 Z
會將 doms
展開,變成實例的屬性,key
為對應 domObj
的索引, 并且設置實例的 length
屬性。
讀到這里,你可能會有點疑惑,$
最終返回的是 Z
函數的實例,但是 Z
函數明明沒有 dom
的操作方法啊,這些操作方法都定義在 $.fn
身上,為什么 $
可以調用這些方法呢?
其實關鍵在于這句代碼 Z.prototype = $.fn
,這句代碼將 Z
的 prototype
指向 $.fn
,這樣,Z
的實例就繼承了 $.fn
的方法。
既然這樣就已經讓 Z
的實例繼承了 $.fn
的方法,那 zepto.Z.prototype = $.fn
又是為什么呢?
如果我們再看源碼,會發現有這樣的一個方法:
zepto.isZ = function(object) { return object instanceof zepto.Z}
這個方法是用來判讀一個對象是否為 zepto 對象,這是通過判斷這個對象是否為 zepto.Z
的實例來完成的,因此需要將 zepto.Z
和 Z
的 prototype
指向同一個對象。 isZ
方法會在 init
中用到,后面也會介紹。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。