91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JS中數組遍歷方法 for 、forEach() 、for/in、for/of有什么區別

發布時間:2020-10-29 10:05:09 來源:億速云 閱讀:134 作者:小新 欄目:web開發

這篇文章主要介紹JS中數組遍歷方法 for 、forEach() 、for/in、for/of有什么區別,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

我們有多種方法來遍歷 JavaScript 的數組或者對象,而它們之間的區別非常讓人疑惑。Airbnb 編碼風格禁止使用 for/in 與 for/of,你知道為什么嗎?

這篇文章將詳細介紹以下 4 種循環語法的區別:

  • for (let i = 0; i < arr.length; ++i)
  • arr.forEach((v, i) => { /* ... */ })
  • for (let i in arr)
  • for (const v of arr)

語法

使用forfor/in,我們可以訪問數組的下標,而不是實際的數組元素值:

for (let i = 0; i < arr.length; ++i) {
    console.log(arr[i]);
}

for (let i in arr) {
    console.log(arr[i]);
}

使用for/of,則可以直接訪問數組的元素值:

for (const v of arr) {
    console.log(v);
}

使用forEach(),則可以同時訪問數組的下標與元素值:

arr.forEach((v, i) => console.log(v));

非數字屬性

JavaScript 的數組就是 Object,這就意味著我們可以給數組添加字符串屬性:

const arr = ["a", "b", "c"];

typeof arr; // 'object'

arr.test = "bad"; // 添加非數字屬性

arr.test; // 'abc'
arr[1] === arr["1"]; // true, JavaScript數組只是特殊的Object

4 種循環語法,只有for/in不會忽略非數字屬性:

const arr = ["a", "b", "c"];
arr.test = "bad";

for (let i in arr) {
    console.log(arr[i]); // 打印"a, b, c, bad"
}

正因為如此,使用for/in遍歷數組并不好。

其他 3 種循環語法,都會忽略非數字屬性:

const arr = ["a", "b", "c"];
arr.test = "abc";

// 打印 "a, b, c"
for (let i = 0; i < arr.length; ++i) {
    console.log(arr[i]);
}

// 打印 "a, b, c"
arr.forEach((el, i) => console.log(i, el));

// 打印 "a, b, c"
for (const el of arr) {
    console.log(el);
}

要點: 避免使用for/in來遍歷數組,除非你真的要想要遍歷非數字屬性。可以使用 ESLint 的guard-for-in規則來禁止使用for/in

數組的空元素

JavaScript 數組可以有空元素。以下代碼語法是正確的,且數組長度為 3:

const arr = ["a", , "c"];

arr.length; // 3

讓人更加不解的一點是,循環語句處理['a',, 'c']['a', undefined, 'c']的方式并不相同。

對于['a',, 'c']for/inforEach會跳過空元素,而forfor/of則不會跳過。

// 打印"a, undefined, c"
for (let i = 0; i < arr.length; ++i) {
    console.log(arr[i]);
}

// 打印"a, c"
arr.forEach(v => console.log(v));

// 打印"a, c"
for (let i in arr) {
    console.log(arr[i]);
}

// 打印"a, undefined, c"
for (const v of arr) {
    console.log(v);
}

對于['a', undefined, 'c'],4 種循環語法一致,打印的都是"a, undefined, c"。

還有一種添加空元素的方式:

// 等價于`['a', 'b', 'c',, 'e']`
const arr = ["a", "b", "c"];
arr[5] = "e";

還有一點,JSON 也不支持空元素:

JSON.parse('{"arr":["a","b","c"]}');
// { arr: [ 'a', 'b', 'c' ] }

JSON.parse('{"arr":["a",null,"c"]}');
// { arr: [ 'a', null, 'c' ] }

JSON.parse('{"arr":["a",,"c"]}');
// SyntaxError: Unexpected token , in JSON at position 12

要點: for/inforEach會跳過空元素,數組中的空元素被稱為"holes"。如果你想避免這個問題,可以考慮禁用forEach:

parserOptions:
    ecmaVersion: 2018
rules:
    no-restricted-syntax:
        - error
        - selector: CallExpression[callee.property.name="forEach"]
          message: Do not use `forEach()`, use `for/of` instead

函數的 this

forfor/infor/of會保留外部作用域的this

對于forEach, 除非使用箭頭函數,它的回調函數的 this 將會變化。

使用 Node v11.8.0 測試下面的代碼,結果如下:

"use strict";

const arr = ["a"];

arr.forEach(function() {
    console.log(this); // 打印undefined
});

arr.forEach(() => {
    console.log(this); // 打印{}
});

要點: 使用 ESLint 的no-arrow-callback規則要求所有回調函數必須使用箭頭函數。

Async/Await 與 Generators

還有一點,forEach()不能與 Async/Await 及 Generators 很好的"合作"。

不能在forEach回調函數中使用 await:

async function run() {
  const arr = ['a', 'b', 'c'];
  arr.forEach(el => {
    // SyntaxError
    await new Promise(resolve => setTimeout(resolve, 1000));
    console.log(el);
  });
}

不能在forEach回調函數中使用 yield:

function run() {
  const arr = ['a', 'b', 'c'];
  arr.forEach(el => {
    // SyntaxError
    yield new Promise(resolve => setTimeout(resolve, 1000));
    console.log(el);
  });
}

對于for/of來說,則沒有這個問題:

async function asyncFn() {
    const arr = ["a", "b", "c"];
    for (const el of arr) {
        await new Promise(resolve => setTimeout(resolve, 1000));
        console.log(el);
    }
}

function* generatorFn() {
    const arr = ["a", "b", "c"];
    for (const el of arr) {
        yield new Promise(resolve => setTimeout(resolve, 1000));
        console.log(el);
    }
}

當然,你如果將forEach()的回調函數定義為 async 函數就不會報錯了,但是,如果你想讓forEach按照順序執行,則會比較頭疼。

下面的代碼會按照從大到小打印 0-9:

async function print(n) {
    // 打印0之前等待1秒,打印1之前等待0.9秒
    await new Promise(resolve => setTimeout(() => resolve(), 1000 - n * 100));
    console.log(n);
}

async function test() {
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].forEach(print);
}

test();

要點: 盡量不要在forEach中使用 aysnc/await 以及 generators。

結論

簡單地說,for/of是遍歷數組最可靠的方式,它比for循環簡潔,并且沒有for/inforEach()那么多奇怪的特例。for/of的缺點是我們取索引值不方便,而且不能這樣鏈式調用forEach(). forEach()

使用for/of獲取數組索引,可以這樣寫:

for (const [i, v] of arr.entries()) {
    console.log(i, v);
}

以上是JS中數組遍歷方法 for 、forEach() 、for/in、for/of有什么區別的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

克东县| 广南县| 双流县| 高台县| 读书| 金门县| 额尔古纳市| 淄博市| 盱眙县| 楚雄市| 西乌| 嘉黎县| 汝南县| 双桥区| 通河县| 襄樊市| 富锦市| 永福县| 神木县| 巴楚县| 石河子市| 玉环县| 卫辉市| 九江市| 金乡县| 庆阳市| 大关县| 肇庆市| 西和县| 沐川县| 广德县| 滦南县| 专栏| 前郭尔| 淄博市| 广宗县| 三穗县| 博罗县| 邢台市| 应城市| 长白|