摘要:到這里,源碼分析完了。但是,有兩個致命的特性的遍歷不能保證順序會遍歷所有可枚舉屬性,包括繼承的屬性。的遍歷順序依賴于執(zhí)行環(huán)境,不同執(zhí)行環(huán)境的實現(xiàn)方式可能會不一樣。
小時候,鄉(xiāng)愁是一枚小小的郵票,
我在這頭,
母親在那頭。
長大后,鄉(xiāng)愁是一張窄窄的船票,
我在這頭,
新娘在那頭。
后來啊,
鄉(xiāng)愁是一方矮矮的墳墓,
我在外頭,
母親在里頭。
而現(xiàn)在,
鄉(xiāng)愁是一灣淺淺的海峽,
我在這頭,
大陸在那頭。
——余光中《鄉(xiāng)愁》
本文為讀 lodash 源碼的第三篇,后續(xù)文章會更新到這個倉庫中,歡迎 star:pocket-lodash
gitbook也會同步倉庫的更新,gitbook地址:pocket-lodash
作用與用法compact 函數(shù)用來去除數(shù)組中的假值,并返回由不為假值元素組成的新數(shù)組。
false、null、0、 ""、undefined 和 NaN 都為假值。
例如:
var arr = [1,false,2,null,3,0,4,NaN,5,undefined] _.compact(arr) // 返回 [1,2,3,4,5]源碼
function compact(array) { let resIndex = 0 const result = [] if (array == null) { return result } for (const value of array) { if (value) { result[resIndex++] = value } } return result }
compact 的源碼只有寥寥幾行,相當簡單。
首先判斷傳入的數(shù)組是否為 null 或者 undefined,如果是,則返回空數(shù)組。
然后用 for...of 來取得數(shù)組中每項的值,如果不為假值,則存入新數(shù)組 result 中,最后將新數(shù)組返回。
到這里,源碼分析完了。
但是在看源碼的時候,發(fā)現(xiàn)這里用了 for...of 來做遍歷,其實除了 for...of 外,也可以用 for 或者 for...in 來做遍歷,那為什么最后選了 for...of 呢?
數(shù)組中的for循環(huán)使用 for 循環(huán),很容易就將 compact 中關于循環(huán)部分的源碼改寫成以下形式:
for (let i = 0; i < array.length; i++) { const value = array[i] if (value) { result[resIndex++] = value } }
這樣寫,肯定是沒有問題的,但是不夠簡潔。
for…in再來看 for...in 循環(huán),先來將源碼改寫一下:
for (let index in array) { const value = array[i] if (value) { result[resIndex++] = value } }
先看看MDN上關于 for...in 的用法:
for...in語句以任意順序遍歷一個對象的可枚舉屬性。
關于可枚舉屬性,可以點擊上面的鏈接到MDN上了解一下,這里不做太多的解釋。
在數(shù)組中,數(shù)組的索引是可枚舉屬性,可以用 for...in 來遍歷數(shù)組的索引,數(shù)組中的稀疏部分不存在索引,可以避免用 for 循環(huán)造成無效遍歷的弊端。
但是,for...in 有兩個致命的特性:
for...in 的遍歷不能保證順序
for...in 會遍歷所有可枚舉屬性,包括繼承的屬性。
for...in 的遍歷順序依賴于執(zhí)行環(huán)境,不同執(zhí)行環(huán)境的實現(xiàn)方式可能會不一樣。單憑這一點,就斷然不能在數(shù)組遍歷中使用 for...in,大多數(shù)情況下,順序?qū)τ跀?shù)組的遍歷都相當重要。
關于第二點,先看個例子:
var arr = [1,2,3] arr.foo = "foo" for (let index in arr) { console.log(index) }
在這個例子中,你期望輸出的是 0,1,2,但是最后輸出的可能是 0,1,2,foo (for...in 不能保證順序)。因為 foo 也是可枚舉屬性,在 for..in 會被遍歷出來。
for…of最后來看看 for...of。
當我們在控制臺中打印一個數(shù)組,并將它展開來查看時,會在數(shù)組的原型鏈上發(fā)現(xiàn)一個很特別的屬性 Symbol.iterator。
其實 for...of 循環(huán)內(nèi)部調(diào)用的就是數(shù)組原型鏈上的 Symbol.iterator 方法。
Symbol.iterator 在調(diào)用的時候會返回一個遍歷器對象,這個遍歷器對象中包含 next 方法,for...of 在每次循環(huán)的時候都會調(diào)用 next 方法來獲取值,直到 next 返回的對象中的 done屬性值為 true 時停止。
其實我們也可以手動調(diào)用來模擬遍歷的過程:
const arr = [1,2,3] const iterator = a[Symbol.iterator]() iterator.next() // {value: 1, done: false} iterator.next() // {value: 2, done: false} iterator.next() // {value: 3, done: false} iterator.next() // {value: undefined, done: true}
知道這些原理后,完全可以改寫數(shù)組中的 Symbol.iterator 方法,例如遍歷時將數(shù)組中的值都乘2:
Array.prototype[Symbol.iterator] = function () { let index = 0 const _self = this return { next: function () { if (index < _self.length) { return {value: _self[index++] * 2, done: false} } else { return {done: true} } } } }
使用 Generator 函數(shù)可以寫成以下的形式:
Array.prototype[Symbol.iterator] = function* () { let index = 0 while (index < this.length) { yield this[index++] * 2 } }
因此在不改寫 Symbol.iterator 的情況下,使用 for...of 來遍歷數(shù)組是安全的,因為這個方法是數(shù)組的原生方法。
關于 Iterator 和 Generator 可以點擊參考中的鏈接詳細查看。
參考MDN:迭代器和生成器
Iterator 和 for...of 循環(huán)
Generator 函數(shù)的語法
Lodash源碼講解(3)-compact函數(shù)
MDN:for...of
MDN:for…in
License署名-非商業(yè)性使用-禁止演繹 4.0 國際 (CC BY-NC-ND 4.0)
最后,所有文章都會同步發(fā)送到微信公眾號上,歡迎關注,歡迎提意見:
作者:對角另一面
文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/92209.html
摘要:首先我們先說一下這個函數(shù)的作用,這個函數(shù)接收一個數(shù)組作為參數(shù)然后將數(shù)組中所有通過布爾轉(zhuǎn)換可以變?yōu)榈闹等コ龔亩梢粋€新的數(shù)組。 原文首發(fā)于Lodash源碼講解 這是我們閱讀Lodash源碼的第3篇博客,在這篇文章里我們來學習一下Lodash的compact方法。 compact函數(shù)內(nèi)部沒有依賴別的函數(shù),讓我們先來看一下compact函數(shù)的源碼。 /** * Creates an ar...
摘要:從表中可以看到,比較運算符的優(yōu)先級為,而三元表達式條件運算符的優(yōu)化級為,因此可以確定比較運算符的優(yōu)先級要比三元表達式的要高,循環(huán)條件其實等價于第二種寫法。從上表中也可以看出前綴自增比比較運算符的優(yōu)化級要高。 我悟出權力本來就是不講理的——蟑螂就是海米;也悟出要造反,內(nèi)心必須強大到足以承受任何后果才行。——北島《城門開》 本文為讀 lodash 源碼的第十篇,后續(xù)文章會更新到這個倉庫中...
摘要:文檔地址中文文檔英文文檔源碼地址創(chuàng)建一個新數(shù)組,包含原數(shù)組中所有的非假值元素。例如和都是被認為是假值。下面對比一下兩者效率,如下圖傳送門可以看到使用更快,如果沒有兼容性需求,還是使用原生函數(shù)比較好。 百忙之中(閑來無事)想抽點時間好好讀一下源碼,于是就選了Lodash來寫一個系列罷。讀源碼順序就按照loadsh文檔順序來。 文檔地址:中文文檔?? 英文文檔源碼地址:gayhub ...
摘要:作用與用法是的內(nèi)部函數(shù),之前在源碼分析之緩存介紹過一種這樣的數(shù)據(jù)結構這是一個二維數(shù)組,每項中的第一項作為緩存對象的,第二項為緩存的值。 這個世界需要一個特定的惡人,可以供人們指名道姓,千夫所指:全都怪你?!迳洗簶洹懂斘艺勁懿綍r我談些什么》 本文為讀 lodash 源碼的第六篇,后續(xù)文章會更新到這個倉庫中,歡迎 star:pocket-lodash gitbook也會同步倉庫的更新...
摘要:依賴源碼分析之緩存使用方式的進一步封裝源碼分析之源碼分析之源碼分析之的實現(xiàn)源碼分析之源碼分析的調(diào)用如果有傳遞,則先調(diào)用,使用生成要比較數(shù)組的映射數(shù)組。循環(huán)完畢,沒有在第二個數(shù)組中發(fā)現(xiàn)相同的項時,將該項存入數(shù)組中。 外部世界那些破舊與貧困的樣子,可以使我內(nèi)心世界得到平衡。——卡爾維諾《煙云》 本文為讀 lodash 源碼的第十七篇,后續(xù)文章會更新到這個倉庫中,歡迎 star:pocke...
閱讀 1784·2021-09-22 15:10
閱讀 1277·2021-09-07 09:58
閱讀 2347·2019-08-30 15:44
閱讀 1648·2019-08-26 18:29
閱讀 2047·2019-08-26 13:35
閱讀 770·2019-08-26 13:31
閱讀 729·2019-08-26 11:42
閱讀 1074·2019-08-23 18:39