讀Zepto源碼之IOS3模塊

分類:IT技術 時間:2017-09-30

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

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

源碼版本

本文閱讀的源碼為 zepto1.2.0

GitBook

《reading-zepto》

trim

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

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

也是常規的做法,如果 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])

參數

  • 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模塊

附文

  • 譯:怎樣處理 Safari 移動端對圖片資源的限制

參考

  • Array.prototype.reduce()

License

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

作者:對角另一面


Tags: prototype reduce 源碼 trim 空格 accumulator

文章來源:


ads
ads

相關文章
ads

相關文章

ad