IOS3
模塊是針對 IOS
的兼容模塊,實現了兩個經常使用方法的兼容,這兩個方法分別是 trim
和 reduce
。javascript
讀 Zepto 源碼系列文章已經放到了github上,歡迎star: reading-zeptojava
本文閱讀的源碼爲 zepto1.2.0ios
《reading-zepto》git
if (String.prototype.trim === undefined) // fix for iOS 3.2 String.prototype.trim = function(){ return this.replace(/^\s+|\s+$/g, '') }
看註釋, trim
是爲了兼容 ios3.2
的。github
也是常規的作法,若是 String
的 prototype
上沒有 trim
方法,則本身實現一個。數組
實現的方式也簡單,就是用正則將開頭和結尾的空格去掉。^\s+
這段是匹配開頭的空格,\s+$
是匹配結尾的空格。微信
// 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])this
參數:
initialValue
)reduce
的數組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
)時,拋出類型錯誤。
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
能獲取到值。
這段還巧妙地用了 ++k
和 k++
。若是 k
在對象 t
中存在時,則賦值給 accumulator
後 k
再自增,不然用 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
做爲參數傳遞給回調函數,直至數組耗盡,而後將結果返回。
署名-非商業性使用-禁止演繹 4.0 國際 (CC BY-NC-ND 4.0)
最後,全部文章都會同步發送到微信公衆號上,歡迎關注,歡迎提意見:
做者:對角另外一面