摘要:用法與參數(shù)要理解這段代碼,先來看一下的用法和參數(shù)用法參數(shù)回調(diào)函數(shù),有如下參數(shù)上一個(gè)回調(diào)函數(shù)返回的值或者是初始值當(dāng)前值當(dāng)前值在數(shù)組中的索引調(diào)用的數(shù)組初始值,如果沒有提供,則為數(shù)組的第一項(xiàng)。接下來,檢測(cè)回調(diào)函數(shù)是否為,如果不是,拋出類型錯(cuò)誤。
IOS3 模塊是針對(duì) IOS 的兼容模塊,實(shí)現(xiàn)了兩個(gè)常用方法的兼容,這兩個(gè)方法分別是 trim 和 reduce 。
讀 Zepto 源碼系列文章已經(jīng)放到了github上,歡迎star: reading-zepto
源碼版本本文閱讀的源碼為 zepto1.2.0
GitBook《reading-zepto》
trimif (String.prototype.trim === undefined) // fix for iOS 3.2 String.prototype.trim = function(){ return this.replace(/^s+|s+$/g, "") }
看注釋, trim 是為了兼容 ios3.2 的。
也是常規(guī)的做法,如果 String 的 prototype 上沒有 trim 方法,則自己實(shí)現(xiàn)一個(gè)。
實(shí)現(xiàn)的方式也簡(jiǎn)單,就是用正則將開頭和結(jié)尾的空格去掉。^s+ 這段是匹配開頭的空格,s+$ 是匹配結(jié)尾的空格。
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 }用法與參數(shù)
要理解這段代碼,先來看一下 reduce 的用法和參數(shù):
用法:
arr.reduce(callback[, initialValue])
參數(shù):
callback: 回調(diào)函數(shù),有如下參數(shù)
accumulator: 上一個(gè)回調(diào)函數(shù)返回的值或者是初始值(initialValue)
currentValue: 當(dāng)前值
currentIndex: 當(dāng)前值在數(shù)組中的索引
array: 調(diào)用 reduce 的數(shù)組
initialValue: 初始值,如果沒有提供,則為數(shù)組的第一項(xiàng)。如果數(shù)組為空數(shù)組,而又沒有提供初始值時(shí),會(huì)報(bào)錯(cuò)
檢測(cè)參數(shù)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()
首先檢測(cè)是否為 undefined 或者 null ,如果是,則報(bào)類型錯(cuò)誤。這里有一點(diǎn)值得注意的,判斷是否為 undefined 時(shí),用了 void 0 的返回值,因?yàn)?void 操作符返回的結(jié)果都為 undefined ,這是為了避免 undefined 被重新賦值,出現(xiàn)誤判的情況。
接下來,將數(shù)組轉(zhuǎn)換成對(duì)象,用變量 t 來保存,后面會(huì)看到,遍歷用的是 for...in 來處理。為什么不直接用 for 來處理數(shù)組呢?因?yàn)?reduce 不會(huì)處理稀疏數(shù)組,所以轉(zhuǎn)換要轉(zhuǎn)換成對(duì)象來處理。
數(shù)組長(zhǎng)度用 len 來保存,這里使用了無符號(hào)位右移操作符 >>> ,確保 len 為非負(fù)整數(shù)。
用 k 來保存當(dāng)前索引,accumulator 為返回值。
接下來,檢測(cè)回調(diào)函數(shù) fun 是否為 function ,如果不是,拋出類型錯(cuò)誤。
在數(shù)組為空,并且又沒有提供初始值(即只有一個(gè)參數(shù) fun)時(shí),拋出類型錯(cuò)誤。
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)
如果參數(shù)至少有兩項(xiàng),則 accumulator 的初始值很簡(jiǎn)單,就是 arguments[1] ,即 initialValue。
如果沒有提供初始值,則迭代索引,直到找到在對(duì)象 t 中存在的索引。注意這里用了 do...while,所以最終結(jié)果,要么是報(bào)類型錯(cuò)誤,要么 accumulator 能獲取到值。
這段還巧妙地用了 ++k 和 k++ 。如果 k 在對(duì)象 t 中存在時(shí),則賦值給 accumulator 后 k 再自增,否則用 k 自增后再和 len 比較,如果超出 len 的長(zhǎng)度,則報(bào)錯(cuò),因?yàn)椴淮嬖谙乱粋€(gè)可以賦給 accumulator 的值。
返回結(jié)果while (k < len){ if(k in t) accumulator = fun.call(undefined, accumulator, t[k], k, t) k++ } return accumulator
要注意,如果沒有提供初始值時(shí),k 是自增后的值,即不再需要處理數(shù)組的第一個(gè)值。
到這里問題就比較簡(jiǎn)單了,就是 while 循環(huán),用 accumulator 保存回調(diào)函數(shù)返回的值,在下一次循環(huán)時(shí),再將 accumulator 作為參數(shù)傳遞給回調(diào)函數(shù),直至數(shù)組耗盡,然后將結(jié)果返回。
系列文章《reading-zepto》
系列文章讀Zepto源碼之代碼結(jié)構(gòu)
讀Zepto源碼之內(nèi)部方法
讀Zepto源碼之工具函數(shù)
讀Zepto源碼之神奇的$
讀Zepto源碼之集合操作
讀Zepto源碼之集合元素查找
讀Zepto源碼之操作DOM
讀Zepto源碼之樣式操作
讀Zepto源碼之屬性操作
讀Zepto源碼之Event模塊
讀Zepto源碼之IE模塊
讀Zepto源碼之Callbacks模塊
讀Zepto源碼之Deferred模塊
讀Zepto源碼之Ajax模塊
讀Zepto源碼之Assets模塊
讀Zepto源碼之Selector模塊
讀Zepto源碼之Touch模塊
讀Zepto源碼之Gesture模塊
附文譯:怎樣處理 Safari 移動(dòng)端對(duì)圖片資源的限制
參考Array.prototype.reduce()
License署名-非商業(yè)性使用-禁止演繹 4.0 國(guó)際 (CC BY-NC-ND 4.0)
最后,所有文章都會(huì)同步發(fā)送到微信公眾號(hào)上,歡迎關(guān)注,歡迎提意見:
作者:對(duì)角另一面
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/88817.html
摘要:讀源碼系列文章已經(jīng)放到了上,歡迎源碼版本本文閱讀的源碼為改寫原有的方法模塊改寫了以上這些方法,這些方法在調(diào)用的時(shí)候,會(huì)為返回的結(jié)果添加的屬性,用來保存原來的集合。方法的分析可以看讀源碼之模塊。 Stack 模塊為 Zepto 添加了 addSelf 和 end 方法。 讀 Zepto 源碼系列文章已經(jīng)放到了github上,歡迎star: reading-zepto 源碼版本 本文閱讀的...
摘要:模塊處理的是表單提交。表單提交包含兩部分,一部分是格式化表單數(shù)據(jù),另一部分是觸發(fā)事件,提交表單。最終返回的結(jié)果是一個(gè)數(shù)組,每個(gè)數(shù)組項(xiàng)為包含和屬性的對(duì)象。否則手動(dòng)綁定事件,如果沒有阻止瀏覽器的默認(rèn)事件,則在第一個(gè)表單上觸發(fā),提交表單。 Form 模塊處理的是表單提交。表單提交包含兩部分,一部分是格式化表單數(shù)據(jù),另一部分是觸發(fā) submit 事件,提交表單。 讀 Zepto 源碼系列文章已...
摘要:所以模塊依賴于模塊,在引入前必須引入模塊。原有的方法分析見讀源碼之樣式操作方法首先調(diào)用原有的方法,將元素顯示出來,這是實(shí)現(xiàn)動(dòng)畫的基本條件。如果沒有傳遞,或者為值,則表示不需要?jiǎng)赢嫞{(diào)用原有的方法即可。 fx 模塊提供了 animate 動(dòng)畫方法,fx_methods 利用 animate 方法,提供一些常用的動(dòng)畫方法。所以 fx_methods 模塊依賴于 fx 模塊,在引入 fx_m...
摘要:的模塊用來獲取節(jié)點(diǎn)中的屬性的數(shù)據(jù),和儲(chǔ)存跟相關(guān)的數(shù)據(jù)。獲取節(jié)點(diǎn)指定的緩存值。如果存在,則刪除指定的數(shù)據(jù),否則將緩存的數(shù)據(jù)全部刪除。為所有下級(jí)節(jié)點(diǎn),如果為方法,則節(jié)點(diǎn)自身也是要被移除的,所以需要將自身也加入到節(jié)點(diǎn)中。 Zepto 的 Data 模塊用來獲取 DOM 節(jié)點(diǎn)中的 data-* 屬性的數(shù)據(jù),和儲(chǔ)存跟 DOM 相關(guān)的數(shù)據(jù)。 讀 Zepto 源碼系列文章已經(jīng)放到了github上,歡...
摘要:模塊基于上的事件的封裝,利用屬性,封裝出系列事件。這個(gè)判斷需要引入設(shè)備偵測(cè)模塊。然后是監(jiān)測(cè)事件,根據(jù)這三個(gè)事件,可以組合出和事件。其中變量對(duì)象和模塊中的對(duì)象的作用差不多,可以先看看讀源碼之模塊對(duì)模塊的分析。 Gesture 模塊基于 IOS 上的 Gesture 事件的封裝,利用 scale 屬性,封裝出 pinch 系列事件。 讀 Zepto 源碼系列文章已經(jīng)放到了github上,歡...
閱讀 1387·2021-09-24 10:26
閱讀 1697·2019-08-30 14:14
閱讀 2108·2019-08-29 16:54
閱讀 367·2019-08-29 14:09
閱讀 1478·2019-08-29 12:55
閱讀 934·2019-08-28 18:13
閱讀 1584·2019-08-26 13:39
閱讀 2571·2019-08-26 11:43