雖然最近工做中沒有怎麼用 zepto ,可是聽說 zepto 的源碼比較簡單,並且網上的資料也比較多,因此我就挑了 zepto 下手,但願能爲之後閱讀其餘框架的源碼打下基礎吧。javascript
本文閱讀的源碼爲 zepto1.2.0html
閱讀zepto以前須要瞭解 javascript 原型鏈和閉包的知識,推薦閱讀王福朋的這篇文章:深刻理解 Javascript 原型和閉包,寫得很詳細,也很是易於閱讀。java
var Zepto = (function () {
...
})()
window.Zepto = Zepto
window.$ === undefined && (window.$ = Zepto)複製代碼
若是在編輯器中將 zepto 的源碼摺疊起來,看到的就跟上面的代碼同樣。git
zepto 的核心是一個閉包,加載完畢後當即執行。而後暴露給全局變量 zepto
,若是 $
沒有定義,也將 $
賦值爲 zepto
。github
在這部分中,咱們先不關注 zepto 的具體實現,只看核心的結構,所以我將zepto中的邏輯先移除,得出以下的核心結構:segmentfault
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 = $.fn
return $複製代碼
在源碼中,能夠看出, $
實際上是一個函數,同時在 $
身上又掛了不少屬性和方法(這裏體如今 $.fn
身上,其餘的會在後續的文章中談到)。微信
咱們在使用 zepto 的時候,會用 $
去獲取 dom
,而且在這些 dom
對象身上都有 zepto 定義的各類各樣的操做方法。閉包
從上面的僞代碼中,能夠看到,$
其實調用了 zepto.init()
方法,在 init
方法中,會獲取到 dom
元素集合,而後將集合交由 zepto.Z()
方法處理,而 zepto.Z
方法返回的是函數 Z
的一個實例。框架
函數 Z
會將 doms
展開,變成實例的屬性,key
爲對應 domObj
的索引, 而且設置實例的 length
屬性。dom
讀到這裏,你可能會有點疑惑,$
最終返回的是 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
中用到,後面也會介紹。
最後,全部文章都會同步發送到微信公衆號上,歡迎關注,歡迎提意見: