詳細(xì)談?wù)凧avaScript中循環(huán)之間的差異
前言
在 JavaScript 中使用循環(huán)時(shí),需要正確定義兩個(gè)關(guān)鍵內(nèi)容:可枚舉屬性(enumerable properties)和可迭代對(duì)象(iterable objects)。
可枚舉的屬性
可枚舉對(duì)象的一個(gè)定義特征是,當(dāng)我們通過(guò)賦值運(yùn)算符將屬性賦值給對(duì)象時(shí),我們將內(nèi)部可枚舉標(biāo)志(enumerable)設(shè)置為 true。這是默認(rèn)值。
但是,我們可以通過(guò)將其設(shè)置為 false 來(lái)更改此行為。
經(jīng)驗(yàn)法則是,可枚舉屬性總是出現(xiàn)在 for...in 循環(huán)中。
讓我們看看這一點(diǎn):
const users = {} users.languages = 'JavaScript' Object.getOwnPropertyDescriptor(users, 'languages') // output -> { value: 'JavaScript', writable: true, enumerable: true, configurable: true } // 在循環(huán)中對(duì)我們使用的屬性進(jìn)行更多的控制 Object.defineProperty(users, 'role', { value: 'Admin', writable: true, enumerable: false }) for (const item in users) { console.log(item) // languages }
可以看到,我們?yōu)?users 變量添加了一個(gè) languages 屬性,使用 Object.getOwnPropertyDescriptor 方法輸出 languages 屬性描述符的 enumerable 屬性為 true。
使用 Object.defineProperty 為添加 role 屬性,并將 enumerable 設(shè)置為 false,在 for...in 循環(huán)中并沒(méi)有輸出 role 屬性。即 for...in 循環(huán)中的屬性為可枚舉屬性。
可迭代對(duì)象
如果一個(gè)對(duì)象定義了它的迭代行為,那么它是可迭代的。在本例中,將在 for...of 構(gòu)造中循環(huán)的值將定義其迭代行為??傻膬?nèi)置類型包括 Array、String、Set 和 Map 對(duì)象不可迭代,因?yàn)樗鼪](méi)有指定 @iterator 方法。
基本上,在 JavaScript 中,所有可迭代對(duì)象都是可枚舉對(duì)象,但并非所有可枚舉對(duì)象都是可迭代對(duì)象。
這里有一種概念化的方法:for...in 查找數(shù)據(jù)中的對(duì)象,而 for...of 查找重復(fù)序列。
讓我們看看這一切在與 Array 數(shù)據(jù)類型一起使用時(shí)的效果:
const languages = ['JavaScript', 'Python', 'Go'] // 與 for...in 循環(huán)一起使用 for (const language in languages) { console.log(language) } // output // 0 // 1 // 2 // 與 for...of 循環(huán)一起使用 for (const language of languages) { console.log(author) } // output -> JavaScript Python Go
在使用這種構(gòu)造時(shí),需要牢記的一點(diǎn)是,如果調(diào)用了 typeof,并且輸出為 object,那么您可以使用 for...in 循環(huán)。
讓我們看看這個(gè)對(duì) languages 變量的操作:
typeof languages // "object" -> 因此我們可以在中使用 for
乍一看,這可能令人驚訝,但需要注意的是,數(shù)組是一種特殊類型的對(duì)象,以索引為鍵。知道 for...in 將在構(gòu)造中查找對(duì)象可以極大地幫助我們。當(dāng) for...in 循環(huán)找到一個(gè)對(duì)象時(shí),它將在每個(gè)鍵上循環(huán)。
我們可以將 for ..in 循環(huán)在 languages 數(shù)組上的方式可視化如下:
const languages = { 0: 'JavaScript', 1: 'Python', 2: 'Go' }
注意:如果它可以被追蹤到一個(gè)對(duì)象(或者從對(duì)象原型鏈繼承它),for...in 將以沒(méi)有特定順序遍歷鍵。
同時(shí),如果它實(shí)現(xiàn)了一個(gè)迭代器 for.. of 構(gòu)造,它將在每次迭代中循環(huán)遍歷該值。
在 forEach 與 map 方法
雖然 forEach 和 map 方法可以用來(lái)實(shí)現(xiàn)相同的目標(biāo),但它們的行為和性能特性有所不同。
在基本級(jí)別,當(dāng)函數(shù)被調(diào)用時(shí),它們都會(huì)接收一個(gè)回調(diào)作為參數(shù)。
考慮以下片段:
const scoresEach = [2, 4 ,8, 16, 32] const scoresMap = [2, 4 ,8, 16, 32] const square = (num) => num * num
讓我們?cè)敿?xì)介紹一下它們?cè)诓僮魃系囊恍┎町悺?/p>
forEach 返回 undefined,而 map 返回一個(gè)新的 array:
let newScores = [] const resultWithEach = scoresEach.forEach(score => { const newScore = square(score) newScores.push(newScore) }) const resultWithMap = scoresMap.map(square) console.log(resultWithEach) // undefined console.log(resultWithMap) // [4, 16, 64, 256, 1024]
Map 是一個(gè)純函數(shù),同時(shí) forEach 執(zhí)行一些突變:
console.log(newScores) // [4, 16, 64, 256, 1024]
在我看來(lái),map 支持函數(shù)式編程范式。我們不必總是執(zhí)行突變來(lái)獲得期望的結(jié)果,不像 forEach,我們必須突變 newScores 變量。在每次運(yùn)行時(shí),當(dāng)提供相同的輸入時(shí),map 函數(shù)將產(chǎn)生相同的結(jié)果。同時(shí),forEach 對(duì)應(yīng)項(xiàng)將從上一個(gè)突變的先前值中提取。
鏈?zhǔn)秸{(diào)用
使用 map 可以進(jìn)行鏈?zhǔn)秸{(diào)用,因?yàn)榉祷氐慕Y(jié)果是一個(gè)數(shù)組。因此,可以對(duì)結(jié)果立即調(diào)用任何其他數(shù)組方法。換句話說(shuō),我們可以調(diào)用 filter、reduce、some 等方法。這在 forEach 中是不可能的,因?yàn)榉祷氐闹禐?undefined 的。
性能
map 方法的性能往往優(yōu)于 forEach 方法。
檢查使用 map 和 forEach 實(shí)現(xiàn)的等效代碼塊的性能。平均而言,您將看到 map 函數(shù)的執(zhí)行速度至少快 50%。
結(jié)論
在上面討論的所有循環(huán)結(jié)構(gòu)中,給我們最多控制的是 for..of 循環(huán)。我們可以將其與關(guān)鍵字 return、continue 和 break 一起使用。這意味著我們可以指定對(duì)數(shù)組中的每個(gè)元素要發(fā)生什么,以及是否要提前離開(kāi)或跳過(guò)。
到此這篇關(guān)于JavaScript中循環(huán)之間差異的文章就介紹到這了,更多相關(guān)JavaScript循環(huán)差異內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js常用方法、檢查是否有特殊字符串、倒序截取字符串操作完整示例
這篇文章主要介紹了js常用方法、檢查是否有特殊字符串、倒序截取字符串操作,結(jié)合完整實(shí)例形式分析了JavaScript字符串轉(zhuǎn)換、檢測(cè)、倒序、截取等相關(guān)操作技巧,需要的朋友可以參考下2020-01-01JavaScript實(shí)現(xiàn)網(wǎng)頁(yè)版貪吃蛇游戲
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)網(wǎng)頁(yè)版貪吃蛇游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07關(guān)于JS中setTimeout()無(wú)法調(diào)用帶參函數(shù)問(wèn)題的解決方法
這篇文章主要介紹了關(guān)于JS中setTimeout()無(wú)法調(diào)用帶參函數(shù)問(wèn)題的解決方法,提供了2種解決方法供大家對(duì)比參考,需要的朋友可以參考下2016-06-06js removeChild 障眼法 可能出現(xiàn)的錯(cuò)誤
js removeChild 障眼法之可能出現(xiàn)的錯(cuò)誤,大家看下代碼就知道了。2009-10-10javascript編程實(shí)現(xiàn)棧的方法詳解【經(jīng)典數(shù)據(jù)結(jié)構(gòu)】
這篇文章主要介紹了javascript編程實(shí)現(xiàn)棧的方法,簡(jiǎn)單說(shuō)明了棧的概念、特點(diǎn)并結(jié)合實(shí)例形式分析了javascript棧的定義、入棧、出棧等操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-04-04原生js的數(shù)組除重復(fù)簡(jiǎn)單實(shí)例
下面小編就為大家?guī)?lái)一篇原生js的數(shù)組除重復(fù)簡(jiǎn)單實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-05-05javascript Array.prototype.slice使用說(shuō)明
slice 可以用來(lái)獲取數(shù)組片段,它返回新數(shù)組,不會(huì)修改原數(shù)組。2010-10-10JS實(shí)現(xiàn)完全語(yǔ)義化的網(wǎng)頁(yè)選項(xiàng)卡效果代碼
這篇文章主要介紹了JS實(shí)現(xiàn)完全語(yǔ)義化的網(wǎng)頁(yè)選項(xiàng)卡效果代碼,可實(shí)現(xiàn)基于鼠標(biāo)滑過(guò)及點(diǎn)擊的選項(xiàng)卡切換效果,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-09-09