js 幾種 for 迴圈的區別
阿新 • • 發佈:2022-03-24
1 js 幾種 for 迴圈的區別
測試 loop 型別:
for
forEach
forOf
forin
forof
Object.keys
測試維度:
1. 是否可訪問非索引的屬性
2. 是否會訪問到empty元素
3. 是否可中斷迴圈
4. 是否可訪問原型屬性
5. 是否可訪問不可列舉屬性
6. 是否支援正常非同步
測試用例
const arr = ['a', 'b', 'c'] arr.props = 'test arr' arr.__proto__.protoKey = 'proto key' Object.defineProperty(arr, 'hiddenKey', { value: 'hidden key', writable: false, configurable: false, enumerable: false })
2 for
ESMAScript1 就存在,相容性較強。但語法冗長,不優雅
- 是否可訪問非索引的屬性 否
- 是否可訪問 empty 元素 是,列印輸出 undefined
- 是否可訪問原型鏈屬性 不可
- 是否可訪問不可列舉屬性 不可
- 是否可中斷迴圈 是,continue 中斷本次,break 中斷本趟,return 中斷函式執行
- 是否支援非同步 是,await 表現正常
for (let i = 0; i < arr.length; i++) { console.log(arr[i]) // a b c } delete arr[1] // empty for (let i = 0; i < arr.length; i++) { console.log(arr[i]) // a undefined c } const asyncFn = () => Promise.resolve(1) ;(async () => { for (let i = 0; i < arr.length; i++) { console.log('step1') console.log(await asyncFn()) console.log('step2') } })() /* step1 1 step2 ... */
3 forEach
- 是否可訪問非索引的屬性 否
- 是否可訪問 empty 元素 否,不會執行 empty 的回撥
- 是否可訪問原型鏈屬性 不可
- 是否可訪問不可列舉屬性 不可
- 是否可中斷迴圈 不可,只能使用 return 返回本次回撥
- 是否支援非同步 否,await 表現異常
const asyncFn = () => Promise.resolve(1) arr.forEach(async (v, i) => { console.log('begin',v) console.log(await asyncFn()) console.log('after',v) }) /* begin a begin b begin c 1 after a 1 after b 1 after c */
4 forof
- 是否可訪問非索引的屬性 否
- 是否可訪問 empty 元素 是,列印輸出 undefined
- 是否可訪問原型鏈屬性 不可
- 是否可訪問不可列舉屬性 不可
- 是否可中斷迴圈 是,continue 中斷本次,break 中斷本趟,return 中斷函式執行
- 是否支援非同步 是,await 表現正常
for (const v of arr) {
console.log(v) // a b c
}
for (const v of arr) {
if (v === 'b') continue // // break; return;也可
console.log(v) // a c
}
;(async () => {
for (const v of arr) {
console.log('step1')
console.log(await asyncFn())
console.log('step2')
}
/*
step1
1
step2
...
*/
})()
5 forin
可以訪問原型鏈上的可列舉屬性,如果不需要此功能,考慮結合 hasOwnProperty 或者改用 Object.keys()
- 是否可訪問非索引的屬性 是
- 是否可訪問 empty 元素 不可
- 是否可訪問原型鏈屬性 可
- 是否可訪問不可列舉屬性 不可
- 是否可中斷迴圈 是,continue 中斷本次,break 中斷本趟,return 中斷函式執行
- 是否支援非同步 是,await 表現正常
for (const key in arr) {
console.log(key, arr[key])
/*
0
2
props
protoKey
*/
}
;(async () => {
for (const key in arr) {
console.log('begin')
console.log(await asyncFn())
console.log('after')
}
/*
begin
1
after
...
*/
})()
6 總結
型別 | 是否可訪問非索引的屬性 | 是否會訪問到 empty 元素 | 是否可訪問原型鏈屬性 | 是否可訪問不可列舉屬性 | 是否可中斷迴圈 | 是否支援非同步 |
---|---|---|---|---|---|---|
for | 否 | 是,列印輸出 undefined | 否 | 否 | 是(continue,break,return) | 是(await 表現正常) |
forEach | 否 | 否,不會執行 empty 元素的回撥 | 否 | 否 | 否 | 否,表現異常 |
forof | 否 | 是,列印輸出 undefined | 否 | 否 | 是(continue,break,return) | 是(await 表現正常) |
forin | 是 | 是,列印輸出 undefined | 是 | 否 | 是(continue,break,return) | 是(await 表現正常) |