讀Zepto源碼之IOS3模塊

IOS3 模塊是針對 IOS 的兼容模塊,實現了兩個經常使用方法的兼容,這兩個方法分別是 trimreducejavascript

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

源碼版本

本文閱讀的源碼爲 zepto1.2.0ios

GitBook

reading-zeptogit

trim

if (String.prototype.trim === undefined) // fix for iOS 3.2
  String.prototype.trim = function(){ return this.replace(/^\s+|\s+$/g, '') }複製代碼

看註釋, trim 是爲了兼容 ios3.2 的。github

也是常規的作法,若是 Stringprototype 上沒有 trim 方法,則本身實現一個。數組

實現的方式也簡單,就是用正則將開頭和結尾的空格去掉。^\s+ 這段是匹配開頭的空格,\s+$ 是匹配結尾的空格。微信

reduce

// For iOS 3.x
// from https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduce
if (Array.prototype.reduce === undefined)
  Array.prototype.reduce = function(fun){
    if(this === void 0 || this === null) throw new TypeError()
    var t = Object(this), len = t.length >>> 0, k = 0, accumulator
    if(typeof fun != 'function') throw new TypeError()
    if(len == 0 && arguments.length == 1) throw new TypeError()

    if(arguments.length >= 2)
      accumulator = arguments[1]
    else
      do{
        if(k in t){
          accumulator = t[k++]
          break
        }
        if(++k >= len) throw new TypeError()
      } while (true)

    while (k < len){
      if(k in t) accumulator = fun.call(undefined, accumulator, t[k], k, t)
      k++
    }
    return accumulator
  }複製代碼

用法與參數

要理解這段代碼,先來看一下 reduce 的用法和參數:函數

用法工具

arr.reduce(callback[, initialValue])ui

參數

  • callback: 回調函數,有以下參數
    • accumulator: 上一個回調函數返回的值或者是初始值(initialValue
    • currentValue: 當前值
    • currentIndex: 當前值在數組中的索引
    • array: 調用 reduce 的數組
  • initialValue: 初始值,若是沒有提供,則爲數組的第一項。若是數組爲空數組,而又沒有提供初始值時,會報錯

檢測參數

if(this === void 0 || this === null) throw new TypeError()
var t = Object(this), len = t.length >>> 0, k = 0, accumulator
if(typeof fun != 'function') throw new TypeError()
if(len == 0 && arguments.length == 1) throw new TypeError()複製代碼

首先檢測是否爲 undefined 或者 null ,若是是,則報類型錯誤。這裏有一點值得注意的,判斷是否爲 undefined 時,用了 void 0 的返回值,由於 void 操做符返回的結果都爲 undefined ,這是爲了不 undefined 被從新賦值,出現誤判的狀況。

接下來,將數組轉換成對象,用變量 t 來保存,後面會看到,遍歷用的是 for...in 來處理。爲何不直接用 for 來處理數組呢?由於 reduce 不會處理稀疏數組,因此轉換要轉換成對象來處理。

數組長度用 len 來保存,這裏使用了無符號位右移操做符 >>> ,確保 len 爲非負整數。

k 來保存當前索引,accumulator 爲返回值。

接下來,檢測回調函數 fun 是否爲 function ,若是不是,拋出類型錯誤。

在數組爲空,而且又沒有提供初始值(即只有一個參數 fun)時,拋出類型錯誤。

accumulator初始值

if(arguments.length >= 2)
  accumulator = arguments[1]
else
  do{
    if(k in t){
      accumulator = t[k++]
      break
    }
    if(++k >= len) throw new TypeError()
  } while (true)複製代碼

若是參數至少有兩項,則 accumulator 的初始值很簡單,就是 arguments[1] ,即 initialValue

若是沒有提供初始值,則迭代索引,直到找到在對象 t 中存在的索引。注意這裏用了 do...while,因此最終結果,要麼是報類型錯誤,要麼 accumulator 能獲取到值。

這段還巧妙地用了 ++kk++ 。若是 k 在對象 t 中存在時,則賦值給 accumulatork 再自增,不然用 k 自增後再和 len 比較,若是超出 len 的長度,則報錯,由於不存在下一個能夠賦給 accumulator 的值。

返回結果

while (k < len){
  if(k in t) accumulator = fun.call(undefined, accumulator, t[k], k, t)
  k++
}
return accumulator複製代碼

要注意,若是沒有提供初始值時,k 是自增後的值,即再也不須要處理數組的第一個值。

到這裏問題就比較簡單了,就是 while 循環,用 accumulator 保存回調函數返回的值,在下一次循環時,再將 accumulator 做爲參數傳遞給回調函數,直至數組耗盡,而後將結果返回。

系列文章

reading-zepto

系列文章

  1. 讀Zepto源碼之代碼結構
  2. 讀Zepto源碼以內部方法
  3. 讀Zepto源碼之工具函數
  4. 讀Zepto源碼之神奇的$
  5. 讀Zepto源碼之集合操做
  6. 讀Zepto源碼之集合元素查找
  7. 讀Zepto源碼之操做DOM
  8. 讀Zepto源碼之樣式操做
  9. 讀Zepto源碼之屬性操做
  10. 讀Zepto源碼之Event模塊
  11. 讀Zepto源碼之IE模塊
  12. 讀Zepto源碼之Callbacks模塊
  13. 讀Zepto源碼之Deferred模塊
  14. 讀Zepto源碼之Ajax模塊
  15. 讀Zepto源碼之Assets模塊
  16. 讀Zepto源碼之Selector模塊
  17. 讀Zepto源碼之Touch模塊
  18. 讀Zepto源碼之Gesture模塊

附文

參考

License

署名-非商業性使用-禁止演繹 4.0 國際 (CC BY-NC-ND 4.0)

最後,全部文章都會同步發送到微信公衆號上,歡迎關注,歡迎提意見:

做者:對角另外一面

相關文章
相關標籤/搜索