讀Zepto源碼之集合操作

来源:http://www.cnblogs.com/hefty/archive/2017/05/22/6887780.html
-Advertisement-
Play Games

接下來幾個篇章,都會解讀 zepto 中的跟 相關的方法,也即源碼 對象中的方法。 讀Zepto源碼系列文章已經放到了github上,歡迎star: "reading zepto" 源碼版本 本文閱讀的源碼為 "zepto1.2.0" .forEach() 因為 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

License: CC BY-NC-ND 4.0

作者:對角另一面


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 有這麼一個有趣的問題,問: 有這麼一個不重覆的自然數數組,自然數長度為N,而數組長度為N 2,依次隨機把自然數放進數組中,請找出2個沒有被放進去的自然數。 例如:這個自然數數組是[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]這十個數,某次隨機放入的順序是[2, 1, 3, 5, 7, ...
  • 【題目描述】 小南有一套可愛的玩具小人,它們各有不同的職業。有一天,這些玩具小人把小南的眼鏡藏了起來。小南發現玩具小人們圍成了一個圈,它們有的面朝國內,有的面朝圈外。如下圖: 這時singer告訴小南一個謎題:“眼鏡藏在我左數第3個玩具小人的右數第1個玩具小人的左數第2個玩具小人那裡。” 小南發現, ...
  • 1.類的載入過程 JVM將類載入過程分為三個步驟:裝載(Load),鏈接(Link)和初始化(Initialize)鏈接又分為三個步驟,如下圖所示: 1) 裝載:查找並載入類的二進位數據; 2)鏈接: 驗證:確保被載入類的正確性; 準備:為類的靜態變數分配記憶體,並將其初始化為預設值; 解析:把類中的 ...
  • 三個月就這麼悄悄溜走了,本K對於前端雖然有了一定的認識,但對一些方面還是處於一種比較萌幣的狀態,就在這種萌幣狀態下,本K又跟著大神浩開始了後臺語言—PHP語言的學習。PHP的學習對於學過其他語言的人來說,是非常easy的(原因後續會提及),K在初次接觸的時候也就僅僅是對一些PHP的寫法有點膈應而已. ...
  • 時間複雜度上,紅黑樹在平均情況下插入,查找以及刪除上都達到了lgN的時間複雜度。 那麼有沒有查找效率更高的數據結構呢,答案就是本文接下來要介紹了散列表,也叫哈希表(Hash Table) 什麼是哈希表 哈希表就是一種以 鍵-值(key-indexed) 存儲數據的結構,我們只要輸入待查找的值即key ...
  • 設計模式一--單例設計模式 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 一、定義 Singleton Pattern: 確保一個類只有一個實例,並且自行實例化並向整個系統提供這個實例。 二、分類 餓漢式單例類:類載入時就進行對象的實例化 懶漢式單例類:第一次引用類時,才進行對象的實例化。 ...
  • ES6新語法於2015年發佈;而我這個前端小白在17年才接觸到。慚愧慚愧!!不過到目前為止,似乎只有FireFox和Chrome對ES6的支持相對良好。不過既然人家ES6已經出來了,還是要跟上技術的潮流。 ES6給我的感覺就是讓js越來越靠近傳統的編程語言,如java;比如裡面的面向對象的思想和語法 ...
  • 滑鼠事件是Web 開發中最常用的一類事件,畢竟滑鼠還是最主要的定位設備。DOM3 級事件中定義了9 個滑鼠事件,簡介如下。 click:在用戶單擊主滑鼠按鈕(一般是左邊的按鈕)或者按下回車鍵時觸發。這一點對確保易訪問性很重要,意味著onclick 事件處理程式既可以通過鍵盤也可以通過滑鼠執行。 db ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...