讀Zepto源碼之集合操作

接下來幾個篇章,都會解讀 zepto 中的跟 dom 相關的方法,也即源碼 $.fn 對象中的方法。

讀Zepto源碼系列文章已經放到了github上,歡迎star: reading-zepto

源碼版本

本文閱讀的源碼為 zepto1.2.0

.forEach()

forEach: emptyArray.forEach

因為 zepto 的 dom 集合是類數組,所以這里只是簡單地復制了數組的 forEach 方法。

具體的 forEach 的用法見文檔:Array.prototype.forEach()

.reduce()

reduce: emptyArray.reduce

簡單地復制了數組的 reduce 方法。

具體的 reduce 的用法見文檔:Array.prototype.reduce()

.push()

push: emptyArray.push

簡單地復制了數組的 push 方法。

具體的 push 的用法見文檔:Array.prototype.push()

.sort()

sort: emptyArray.sort

簡單地復制了數組的 sort 方法。

具體的 sort 的用法見文檔:Array.prototype.sort()

.splice()

splice: emptyArray.splice

簡單地復制了數組的 splice 方法。

具體的 splice 的用法見文檔:Array.prototype.splice()

.indexOf()

indexOf: emptyArray.indexOf

簡單地復制了數組的 indexOf 方法。

具體的 indexOf 的用法見文檔:Array.prototype.indexOf()

.get()

get: function(idx) {
  return idx === undefined ? slice.call(this) : this[idx >= 0 ? idx : idx + this.length]
},

這個方法用來獲取指定索引值的元素。

不傳參(idx === undefined)時,不傳參調用數組的 slice 方法,將集合中的所有元素返回。

當傳遞的參數大于或等于零(idx)時,返回相應索引值的元素 this[idx] ,如果為負數,則倒數返回this.[idx + this.length]。

例如 $('li').get(-1) 返回的是倒數第1個元素,也即最后一個元素

.toArray()

toArray: function() { return this.get() }

toArray 方法是將元素的類數組變成純數組。toArray 內部不傳參調用 get 方法,上面已經分析了,當不傳參數時,get 方法調用的是數組方法 slice, 返回的自然就是純數組了。

.size()

size: function() {
  return this.length
}

size 方法返回的是集合中的 length 屬性,也即集合中元素的個數。

.concat()

concat: function() {
  var i, value, args = []
  for (i = 0; i < arguments.length; i++) {
    value = arguments[i]
    args[i] = zepto.isZ(value) ? value.toArray() : value
  }
  return concat.apply(zepto.isZ(this) ? this.toArray() : this, args)
},

數組中也有對應的 concat 方法,為什么不能像上面的方法那樣直接調用呢?

這是因為 $.fn 其實是一個類數組對象,并不是真正的數組,如果直接調用 concat 會直接把整個 $.fn 當成數組的一個 item 合并到數組中。

for (i = 0; i < arguments.length; i++) {
  value = arguments[i]
  args[i] = zepto.isZ(value) ? value.toArray() : value
}

這段是對每個參數進行判斷,如果參數是 zepto 的集合(zepto.isZ(value)),就先調用 toArray 方法,轉換成純數組。

return concat.apply(zepto.isZ(this) ? this.toArray() : this, args)

這段同樣對 this 進行了判斷,如果為 zepto 集合,也先轉換成數組。所以調用 concat 后返回的是純數組,不再是 zepto 集合。

.map()

map: function(fn) {
  return $($.map(this, function(el, i) { return fn.call(el, i, el) }))
}

map 方法的內部調用的是 zepto 的工具函數 $.map ,這在之前已經在《讀Zepto源碼之工具函數》做過了分析。

return fn.call(el, i, el)

map 方法對回調也做了包裝,call 的第一個參數為 el ,因此可以在 map 的回調中通過 this 來拿到每個元素。

map 方法對 $.map 返回的數組調用了 $() 方法,將返回的數組再次包裝成 zepto 對象,因此調用 map 方法后得到的數組,同樣具有 zepto 集合中的方法。

.slice()

slice: function() {
  return $(slice.apply(this, arguments))
}

slice 同樣沒有直接用數組的原生方法,也像 map 方法一樣,將返回的數組再次包裝成 zepto 對象。

.each()

each: function(callback) {
  emptyArray.every.call(this, function(el, idx) {
    return callback.call(el, idx, el) !== false
  })
  return this
},

zeptoeach 方法比較巧妙,在方法內部,調用的其實是數組的 every 方法,every 遇到 false 時就會中止遍歷,zepto 也正是利用 every 這種特性,讓 each 方法也具有了中止遍歷的能力,當 callback 返回的值為布爾值 false 時,中止遍歷,注意這里用了 !==,因為 callback 如果沒有返回值時,得到的值會是 undefined ,這種情況是需要排除的。

同樣,each 的回調中也是可以用 this 拿到每個元素的。

注意,each 方法最后返回的是 this, 所以在 each 調用完后,還可以繼續調用 集合中的其他方法,這就是 zepto 的鏈式調用,這個跟 map 方法中返回 zepto 集合的原理差不多,只不過 each 返回的是跟原來一樣的集合,map 方法返回的是映射后的集合。

.add()

add: function(selector, context) {
  return $(uniq(this.concat($(selector, context))))
}

add 可以傳遞兩個參數,selectorcontext ,即選擇器和上下文。

add 調用 $(selector, context) 來獲取符合條件的集合元素,這在上篇文章《讀Zepto源碼之神奇的$》已經有詳細的論述。

然后調用 concat 方法來合并兩個集合,用內部方法 uniq 來過濾掉重復的項,uniq 方法在《讀Zepto源碼之內部方法》已經有論述。最后也是返回一個 zepto 集合。

系列文章

  1. 讀Zepto源碼之代碼結構
  2. 讀 Zepto 源碼之內部方法
  3. 讀Zepto源碼之工具函數
  4. 讀Zepto源碼之神奇的$

參考

License

最后,所有文章都會同步發送到微信公眾號上,歡迎關注,歡迎提意見:

作者:對角另一面

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,786評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,656評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,697評論 0 379
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,098評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,855評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,254評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,322評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,473評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,014評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,833評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,016評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,568評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,273評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,680評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,946評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,730評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,006評論 2 374

推薦閱讀更多精彩內容