w3school For-each在JavaScript中的數組?




w3c javascript foreach (23)

如何使用JavaScript循環遍歷數組中的所有條目?

我以為它是這樣的:

forEach(instance in theArray)

其中theArray是我的數組,但這似乎是不正確的。


如果你有一個龐大的陣列,你應該用它iterators來獲得一些效率。迭代器是一定的JavaScript集合的性質(如MapSetStringArray)。甚至,for...of使用iterator引擎蓋下。

迭代器通過讓您一次一個地使用列表中的項目來提高效率,就像它們是流一樣。使迭代器特殊的是它如何遍歷集合。其他循環需要預先加載整個集合以便迭代它,而迭代器只需要知道集合中的當前位置。

您可以通過調用迭代器的next方法來訪問當前項。下一個方法將返回value當前項的a和a,boolean以指示何時到達集合的末尾。以下是從數組創建迭代器的示例。

使用如下values()方法將常規數組轉換為迭代器:

    const myArr = [2,3,4]

let it = myArr.values();

console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());

您還可以使用以下方法將常規數組轉換為迭代器Symbol.iterator

const myArr = [2,3,4]

let it = myArr[Symbol.iterator]();

console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());

您還可以將常規array轉換為iterators以下內容:

let myArr = [8, 10, 12];

function makeIterator(array) {
    var nextIndex = 0;
    
    return {
       next: function() {
           return nextIndex < array.length ?
               {value: array[nextIndex++], done: false} :
               {done: true};
       }
    };
};

var it = makeIterator(myArr);

console.log(it.next().value);   // {value: 8, done: false}
console.log(it.next().value);   // {value: 10, done: false}
console.log(it.next().value);   // {value: 12, done: false}
console.log(it.next().value);   // {value: undefined, done: true}

注意

  • 迭代器本質上是可耗盡的。
  • iterable默認情況下不是對象。for..in在這種情況下使用,因為它不是值,而是與鍵一起使用。

你可以iteration protocol here閱讀更多信息。


lambda語法通常不適用於IE 10或更低版本。

我經常使用

[].forEach.call(arrayName,function(value,index){
    console.log("value of the looped element" + value);
    console.log("index of the looped element" + index);
});


If you are a jQuery Fan and already have a jQuery file running, you should reverse the positions of the index and value parameters

$("#ul>li").each(function(**index,value**){
    console.log("value of the looped element" + value);
    console.log("index of the looped element" + index);
});

jQuery方式使用$.map

var data = [1, 2, 3, 4, 5, 6, 7];

var newData = $.map(data, function(element) {
    if (element % 2 == 0) {
        return element;
    }
});

// newData = [2, 4, 6];

從ES6開始:

list = [0, 1, 2, 3]
for (let obj of list) {
    console.log(obj)
}

of避免了相關的怪異in,並使其喜歡的工作for任何其他語言的循環,並let結合i作為函數內相對於內環路。

{}當只有一個命令時(例如在上面的例子中),可以省略大括號()。


for(let i=0;i<theArray.length;i++){
  console.log(i); //i will have the value of each index
}

編輯 :這個答案毫無希望地過時了。 有關更現代的方法,請查看陣列上可用的方法 。 感興趣的方法可能是:

  • 的forEach
  • 地圖
  • 過濾
  • 壓縮
  • 降低
  • 一切
  • 一些

JavaScript迭代數組的標準方法是-loop:

var length = arr.length,
    element = null;
for (var i = 0; i < length; i++) {
  element = arr[i];
  // Do something with element
}

但請注意,只有擁有密集數組且每個索引都被一個元素佔用時,此方法才有用。 如果數組是稀疏的,那麼你可能會遇到這種方法的性能問題,因為你會迭代很多在數組中不存在的索引。 在這種情況下, for .. in -loop可能是一個更好的主意。 但是 ,您必須使用適當的安全措施來確保僅對數組的所需屬性(即數組元素)起作用,因為for..in -loop也將在舊版瀏覽器中枚舉,或者如果附加屬性定義為enumerable

ECMAScript 5中 ,陣列原型上將有一個forEach方法,但在舊版瀏覽器中不支持它。 因此,為了能夠始終如一地使用它,您必須具有支持它的環境(例如,服務器端JavaScript的Node.js ),或使用“Polyfill”。 然而,Polyfill對於這個功能是微不足道的,因為它使代碼更容易閱讀,所以它是一個很好的polyfill。


使用循環與ES6 destructuring擴展運算符

雖然一些javascript老手可能認為它很混亂,但是小輩或其他一些人可能覺得它很有用,因此對於ES6的新手來說,解構和擴展運算符的使用已被證明是非常有用的。

以下示例將使用for...of語句和.forEach方法。

實施例6,7和8可以與像任何官能環路被使用.map.filter.reduce.sort.every.some,有關這些方法的詳細信息檢查出數組對象

示例1:正常for...of循環 - 這裡沒有技巧。

let arrSimple = ['a', 'b', 'c'];

for (let letter of arrSimple) {
  console.log(letter);
}

示例2:將單詞拆分為字符

let arrFruits = ['apple', 'orange', 'banana'];

for (let [firstLetter, ...restOfTheWord] of arrFruits) {
  // Create a shallow copy using the spread operator
  let [lastLetter] = [...restOfTheWord].reverse();
  console.log(firstLetter, lastLetter, restOfTheWord);

}

例3:用a key和。循環value

// let arrSimple = ['a', 'b', 'c'];

// Instead of keeping an index in `i` as per example `for(let i = 0 ; i<arrSimple.length;i++)`
// this example will use a multi-dimensional array of the following format type: 
// `arrWithIndex: [number, string][]`

let arrWithIndex = [
  [0, 'a'],
  [1, 'b'],
  [2, 'c'],
];

// Same thing can be achieved using `.map` method
// let arrWithIndex = arrSimple.map((i, idx) => [idx, i]);

// Same thing can be achieved using `Object.entries`
// NOTE: `Object.entries` method doesn't work on internet explorer unless it's polyfilled
// let arrWithIndex = Object.entries(arrSimple);

for (let [key, value] of arrWithIndex) {
  console.log(key, value);
}

示例4:內聯獲取對象屬性

let arrWithObjects = [{
    name: 'Jon',
    age: 32
  },
  {
    name: 'Elise',
    age: 33
  }
];

for (let { name, age: aliasForAge } of arrWithObjects) {
  console.log(name, aliasForAge);
}

示例5:獲取所需內容的深層對象屬性

let arrWithObjectsWithArr = [{
    name: 'Jon',
    age: 32,
    tags: ['driver', 'chef', 'jogger']
  },
  {
    name: 'Elise',
    age: 33,
    tags: ['best chef', 'singer', 'dancer']
  }
];

for (let { name, tags: [firstItemFromTags, ...restOfTags] } of arrWithObjectsWithArr) {
  console.log(name, firstItemFromTags, restOfTags);
}

實施例6:實施例3是否與.forEach

let arrWithIndex = [
  [0, 'a'],
  [1, 'b'],
  [2, 'c'],
];

// Not to be confused here, `forEachIndex` is the real index
// `mappedIndex` was created by "another user", so you can't really trust it

arrWithIndex.forEach(([mappedIndex, item], forEachIndex) => {
  console.log(forEachIndex, mappedIndex, item);
});

實施例7:實施例4是否與.forEach

let arrWithObjects = [{
    name: 'Jon',
    age: 32
  },
  {
    name: 'Elise',
    age: 33
  }
];
// NOTE: Destructuring objects while using shorthand functions 
// are required to be surrounded by parenthesis
arrWithObjects.forEach( ({ name, age: aliasForAge }) => {
  console.log(name, aliasForAge)
});

實施例8:實施例5是否與.forEach

let arrWithObjectsWithArr = [{
    name: 'Jon',
    age: 32,
    tags: ['driver', 'chef', 'jogger']
  },
  {
    name: 'Elise',
    age: 33,
    tags: ['best chef', 'singer', 'dancer']
  }
];

arrWithObjectsWithArr.forEach(({
  name,
  tags: [firstItemFromTags, ...restOfTags]
}) => {
  console.log(name, firstItemFromTags, restOfTags);
});


摘要:

在遍歷數組時,我們通常可能希望實現以下目標之一:

  1. 我們想迭代數組並創建新數組:

    Array.prototype.map

  2. 我們想迭代數組而不創建新數組:

    Array.prototype.forEach

    for..of

在JS中,有許多方法可以實現這兩個目標。然而,有些人比其他人更有條理。下面你可以找到一些常用的方法(最方便的imo)來完成javascript中的數組迭代。

創建新數組: Map

map()是一個位於其上的函數Array.prototype,可以轉換數組的每個元素,然後返回一個數組。map()將回調函數作為參數,並按以下方式工作:

let arr = [1, 2, 3, 4, 5];

let newArr = arr.map((element, index, array) => {
  return element * 2;
})

console.log(arr);
console.log(newArr);

我們map()作為參數傳遞的回調是針對每個元素執行的。然後返回一個與原始數組長度相同的數組。在這個新的數組元素由作為參數傳入的回調函數轉換map()

在不同的差異map和其他循環機制,就像forEach和一個for..of循環是map回報作為新的數組和離開舊陣列完好(除了這樣想,如果你明確地操縱它splice)。

另請注意,map函數的回調提供了當前迭代的索引號作為第二個參數。此外,第三個參數提供了map被調用的數組。有時這些屬性非常有用。

循環使用 forEach

forEach是一個函數,它位於Array.prototype一個回調函數作為參數。然後它為數組中的每個元素執行此回調函數。與map()函數相反,forEach函數不返回任何內容(undefined)。例如:

let arr = [1, 2, 3, 4, 5];

arr.forEach((element, index, array) => {

  console.log(element * 2);

  if (index === 4) {
    console.log(array)
  }
  // index, and oldArray are provided as 2nd and 3th argument by the callback

})

console.log(arr);

就像map函數一樣,forEach回調提供了當前迭代的索引號作為第二個參數。第三個參數也提供了forEach被調用的數組。

循環使用元素 for..of

所述for..of的循環遍歷的陣列(或任何其他迭代的對象)的每一個元素。它的工作方式如下:

let arr = [1, 2, 3, 4, 5];

for(let element of arr) {
  console.log(element * 2);
}

在上面的例子中element代表一個數組元素,arr是我們想要循環的數組。並非名稱element是任意的,我們可以選擇任何其他名稱,如'el'或更適用的聲明。

不要將for..in循環與for..of循環混淆。for..in將循環遍歷數組的所有可枚舉屬性,而for..of循環將僅循環遍歷數組元素。例如:

let arr = [1, 2, 3, 4, 5];

arr.foo = 'foo';

for(let element of arr) {
  console.log(element);
}

for(let element in arr) {
  console.log(element);
}


TL; DR

  • 除非您在保護措施中使用它或者至少知道它為什麼會咬你for-in否則不要使用for-in
  • 你最好的賭注通常是

    • for-of循環(僅限ES2015 +),
    • Array#forEachspec | MDN )(或其親戚等)(僅限ES5 +),
    • 一個簡單的老式for循環,
    • 或保障。

但還有更多值得探索的內容,請繼續閱讀......

JavaScript具有強大的語義,可以循環遍歷數組和類似數組的對象。 我將答案分為兩部分:正版數組的選項,以及類似數組的選項,例如arguments對象,其他可迭代對象(ES2015 +),DOM集合等。

我很快就會注意到,即使在ES5引擎上,您也可以通過將ES2015轉換為ES5來使用ES2015選項。 搜索“ES2015 transpiling”/“ES6 transpiling”了解更多...

好的,讓我們來看看我們的選擇:

對於實際數組

ECMAScript 5有三個選項(“ES5”),目前支持最廣泛的版本,以及ECMAScript 2015添加的兩個選項(“ES2015”,“ES6”):

  1. 用於forEach和相關(ES5 +)
  2. 使用簡單的for循環
  3. 正確使用for-in
  4. 使用for-of (隱式使用迭代器)(ES2015 +)
  5. 明確使用迭代器(ES2015 +)

細節:

1.使用forEach和相關

在任何模糊的現代環境(因此,不是IE8)中,您可以訪問ES5添加的Array功能(直接或使用polyfill),您可以使用forEachspec | MDN ):

var a = ["a", "b", "c"];
a.forEach(function(entry) {
    console.log(entry);
});

forEach接受一個回調函數,並且可選地,在調用該回調時使用一個值(上面沒有使用)。 為數組中的每個條目調用回調,按順序跳過稀疏數組中不存在的條目。 雖然我上面只使用了一個參數,但回調是用三個來調用的:每個條目的值,該條目的索引,以及對你要迭代的數組的引用(如果你的函數還沒有方便的話) )。

除非您支持IE8等過時的瀏覽器(截至2016年9月,NetApps的市場份額僅超過4%),您可以愉快地在沒有墊片的通用網頁中使用forEach 。 如果您確實需要支持過時的瀏覽器,則可以輕鬆完成每個填充/填充(為幾個選項搜索“es5 shim”)。

forEach的好處是您不必在包含範圍內聲明索引和值變量,因為它們作為參數提供給迭代函數,因此很好地限定了該迭代。

如果您擔心為每個數組條目調用函數的運行時成本,請不要這樣做; blog.niftysnippets.org/2012/02/foreach-and-runtime-cost.html

另外, forEach是“循環通過它們”的功能,但ES5定義了其他一些有用的“按照你的方式完成數組並做事”的功能,包括:

  • every (在第一次回調返回false或falsey時停止循環)
  • some (第一次回調返回true時停止循環或者真空)
  • filter (創建一個新數組,包括filter函數返回true元素,省略返回false元素)
  • map (根據回調返回的值創建一個新數組)
  • reduce (通過重複調用回調來構建一個值,傳入以前的值;查看詳細信息的規範;對於匯總數組的內容和許多其他內容很有用)
  • reduceRight (如reduce ,但以降序而不是升序運行)

2.使用簡單的for循環

有時舊的方式是最好的:

var index;
var a = ["a", "b", "c"];
for (index = 0; index < a.length; ++index) {
    console.log(a[index]);
}

如果數組的長度在循環期間不會改變,並且它在性能敏感的代碼中(不太可能),那麼在前面抓取長度的稍微複雜的版本可能會快一點:

var index, len;
var a = ["a", "b", "c"];
for (index = 0, len = a.length; index < len; ++index) {
    console.log(a[index]);
}

和/或向後計數:

var index;
var a = ["a", "b", "c"];
for (index = a.length - 1; index >= 0; --index) {
    console.log(a[index]);
}

但是使用現代JavaScript引擎,你很少需要榨取最後一點果汁。

在ES2015及更高版本中,您可以將索引和值變量設置為for循環的本地變量:

let a = ["a", "b", "c"];
for (let index = 0; index < a.length; ++index) {
    let value = a[index];
}
//console.log(index); // Would cause "ReferenceError: index is not defined"
//console.log(value); // Would cause "ReferenceError: value is not defined"

當你這樣做時,不僅是value而且還為每個循環迭代重建index ,這意味著在循環體中創建的閉包保持對為該特定迭代創建的index (和value )的引用:

let divs = document.querySelectorAll("div");
for (let index = 0; index < divs.length; ++index) {
    divs[index].addEventListener('click', e => {
        alert("Index is: " + index);
    });
}

如果您有五個div,如果單擊第一個,則“索引為:0”,如果單擊最後一個,則“索引為:4”。 如果您使用var而不是let這將不起作用。

3. 正確使用for-in

你會讓人們告訴你使用for-in ,但這不是for-in的用途for-in循環遍歷對象可枚舉屬性 ,而不是數組的索引。 訂單無法保證 ,即使在ES2015(ES6)中也是如此。 ES2015確實定義了對象屬性的順序(通過[[OwnPropertyKeys]][[Enumerate]] ,以及使用它們的東西,如Object.getOwnPropertyKeys ),但它沒有定義for-in將遵循該順序。 ( 其他答案詳述。)

但是,如果使用適當的安全措施,它可能很有用,特別是對於稀疏數組

// `a` is a sparse array
var key;
var a = [];
a[0] = "a";
a[10] = "b";
a[10000] = "c";
for (key in a) {
    if (a.hasOwnProperty(key)  &&        // These are explained
        /^0$|^[1-9]\d*$/.test(key) &&    // and then hidden
        key <= 4294967294                // away below
        ) {
        console.log(a[key]);
    }
}

請注意兩個檢查:

  1. 該對象具有該名稱的自己的屬性(不是它從原型繼承的那個),和

  2. 密鑰是普通字符串形式的基數為10的數字字符串,其值為<= 2 ^ 32 - 2(即4,294,967,294)。 這個數字來自哪裡? 它是規範中數組索引定義的一部分。 其他數字(非整數,負數,大於2 ^ 32 - 2的數字)不是數組索引。 它是2 ^ 32 - 2的原因是使得最大索引值低於2 ^ 32 - 1 ,這是數組length可以具有的最大值。 (例如,一個數組的長度適合32位無符號整數。) (道具指向RobG, 在我的博客文章評論中指出我以前的測試不太正確。)

在大多數陣列上,每次循環迭代都會增加一小部分開銷,但如果你有一個稀疏數組,它可以是一種更有效的循環方式,因為它只循環實際存在的條目。 例如,對於上面的數組,我們總共循環三次(對於鍵"0""10""10000" - 記住,它們是字符串),而不是10,001次。

現在,您不希望每次都寫這個,所以您可以將它放在您的工具箱中:

function arrayHasOwnIndex(array, prop) {
    return array.hasOwnProperty(prop) && /^0$|^[1-9]\d*$/.test(prop) && prop <= 4294967294; // 2^32 - 2
}

然後我們就像這樣使用它:

for (key in a) {
    if (arrayHasOwnIndex(a, key)) {
        console.log(a[key]);
    }
}

或者如果你只對“大多數情況下足夠好”的測試感興趣,你可以使用它,但是當它接近時,它並不完全正確:

for (key in a) {
    // "Good enough" for most cases
    if (String(parseInt(key, 10)) === key && a.hasOwnProperty(key)) {
        console.log(a[key]);
    }
}

4.使用for-of (隱式使用迭代器)(ES2015 +)

ES2015為JavaScript添加了迭代器 。 使用迭代器的最簡單方法是使用新的for-of語句。 它看起來像這樣:

var val;
var a = ["a", "b", "c"];
for (val of a) {
    console.log(val);
}

輸出:

a
b
c

在封面下,它從數組中獲取一個迭代器並循環遍歷它,從中獲取值。 這沒有使用for-in問題,因為它使用由對象(數組)定義的迭代器,並且數組定義它們的迭代器遍歷它們的條目 (而不是它們的屬性)。 與ES5中的for-in不同for-in訪問條目的順序是其索引的數字順序。

5.明確使用迭代器(ES2015 +)

有時,您可能希望顯式使用迭代器。 你也可以做到這一點,雖然它比起來更笨拙。 它看起來像這樣:

var a = ["a", "b", "c"];
var it = a.values();
var entry;
while (!(entry = it.next()).done) {
    console.log(entry.value);
}

迭代器是與規範中的Iterator定義匹配的對象。 每次調用它時,它的next方法都會返回一個新的結果對象 。 結果對像有一個屬性, done ,告訴我們是否已完成,以及具有該迭代值的屬性value 。 (如果它是false ,則done是可選的,如果undefined ,則value是可選的。)

value的含義取決於迭代器; 數組支持(至少)三個返回迭代器的函數:

  • values() :這是我上面使用的那個。 它返回一個迭代器,其中每個value都是該迭代的數組條目(前面示例中的"a""b""c" )。
  • keys() :返回一個迭代器,其中每個value都是該迭代的關鍵(因此對於我們的a上面是"0" ,然後是"1" ,然後是"2" )。
  • entries() :返回一個迭代器,其中每個value都是該迭代形式[key, value]的數組。

對於類似數組的對象

除了真正的數組之外,還有類似數組的對象,它們具有length屬性和帶有數字名稱的屬性: NodeList實例, arguments像等。我們如何循環其內容?

使用上面的任何數組選項

上面的陣列方法中的至少一些,可能是大多數甚至全部,經常同樣適用於類似數組的對象:

  1. 用於forEach和相關(ES5 +)

    Array.prototype上的各種函數是“故意通用的”,通常可以通過Function#callFunction#apply在類似數組的對像上Function#apply 。 (請參閱本答案末尾的主題提供對象警告 ,但這是一個罕見的問題。)

    假設您想在NodechildNodes屬性上使用forEach 。 你這樣做:

    Array.prototype.forEach.call(node.childNodes, function(child) {
        // Do something with `child`
    });
    

    如果您要做很​​多事情,您可能希望將函數引用的副本獲取到變量中以供重用,例如:

    // (This is all presumably in some scoping function)
    var forEach = Array.prototype.forEach;
    
    // Then later...
    forEach.call(node.childNodes, function(child) {
        // Do something with `child`
    });
    
  2. 使用簡單的for循環

    顯然,一個簡單的for循環適用於類似數組的對象。

  3. 正確使用for-in

    具有與數組相同的安全措施的for-in應該與類似數組的對像一起使用; 上面#1上主機提供的對象的警告可能適用。

  4. 使用for-of (隱式使用迭代器)(ES2015 +)

    for-of將使用對象提供的迭代器(如果有的話); 我們將不得不看到它如何與各種類似數組的對像一起使用,特別是主機提供的對象。 例如,來自querySelectorAllNodeList規範已更新,以支持迭代。 來自getElementsByTagNameHTMLCollection的規範不是。

  5. 明確使用迭代器(ES2015 +)

    看到#4,我們必須看看迭代器是如何發揮作用的。

創建一個真正的數組

其他時候,您可能希望將類似數組的對象轉換為真正的數組。 這樣做非常簡單:

  1. 使用數組的slice方法

    我們可以使用數組的slice方法,就像上面提到的其他方法一樣,“故意通用”,因此可以用於類似數組的對象,如下所示:

    var trueArray = Array.prototype.slice.call(arrayLikeObject);
    

    因此,例如,如果我們想將NodeList轉換為真正的數組,我們可以這樣做:

    var divs = Array.prototype.slice.call(document.querySelectorAll("div"));
    

    請參閱下面的主題提供的對象 。 特別要注意的是,這將在IE8及更早版本中失敗,它們不允許您像this使用主機提供的對象。

  2. 使用擴展語法( ...

    也可以使用ES2015的擴展語法和支持此功能的JavaScript引擎:

    var trueArray = [...iterableObject];
    

    因此,例如,如果我們想將NodeList轉換為真正的數組,使用擴展語法,這變得非常簡潔:

    var divs = [...document.querySelectorAll("div")];
    
  3. 使用Array.from (spec) | (MDN)

    Array.from (ES2015 +,但很容易polyfilled)從類似數組的對象創建一個數組,可選地首先通過映射函數傳遞條目。 所以:

    var divs = Array.from(document.querySelectorAll("div"));
    

    或者,如果您想獲得具有給定類的元素的標記名稱數組,則可以使用映射函數:

    // Arrow function (ES2015):
    var divs = Array.from(document.querySelectorAll(".some-class"), element => element.tagName);
    
    // Standard function (since `Array.from` can be shimmed):
    var divs = Array.from(document.querySelectorAll(".some-class"), function(element) {
        return element.tagName;
    });
    

警告主機提供的對象

如果將Array.prototype函數與主機提供的類似數組的對象(DOM列表和瀏覽器提供的其他內容而不是JavaScript引擎)一起使用,則需要確保在目標環境中進行測試以確保提供主機對象行為正常。 大多數人都表現得很好 (現在),但測試很重要。 原因是你可能想要使用的大多數Array.prototype方法依賴於主機提供的對象,給出了抽象[[HasProperty]]操作的誠實答案。 在撰寫本文時,瀏覽器在這方面做得很好,但5.1規範確實允許主機提供的對象可能不誠實。 它在§8.6.2 ,在該部分開頭附近的大表下面的幾個段落),其中說:

除非另有說明,否則Host對象可以以任何方式實現這些內部方法; 例如,一種可能性是特定主機對象的[[Get]][[Put]]確實獲取並存儲屬性值,但[[HasProperty]]始終生成false

(我無法在ES2015規範中找到相同的措辭,但它仍然是這樣的。)同樣,在撰寫本文時,現代瀏覽器中常見的主機提供的類似數組的對象[例如NodeList實例]正確處理[[HasProperty]] ,但測試很重要。)


如果你想使用forEach()它,它看起來像 -

theArray.forEach ( element => { console.log(element); });

如果你想使用for()它,它看起來像 -

for(let idx = 0; idx < theArray.length; idx++){ let element = theArray[idx]; console.log(element); }



ECMAScript5(Javascript上的版本)與Arrays一起使用。

forEach - 遍歷數組中的每個項目,並為每個項目執行所需的任何操作。

['C', 'D', 'E'].forEach(function(element, index) {
  console.log(element + " is the #" + (index+1) + " in musical scale");
});

// Output
// C is the #1 in musical scale
// D is the #2 in musical scale
// E is the #3 in musical scale

萬一,對使用一些內置功能的陣列操作更感興趣。

map - 它使用回調函數的結果創建一個新數組。當您需要格式化數組的元素時,可以使用此方法。

// Let's upper case the items in the array
['bob', 'joe', 'jen'].map(function(elem) {
  return elem.toUpperCase();
});

// Output: ['BOB', 'JOE', 'JEN']

reduce - 正如名稱所說,它通過調用傳入currenct元素的給定函數和先前執行的結果將數組減少為單個值。

[1,2,3,4].reduce(function(previous, current) {
  return previous + current;
});
// Output: 10
// 1st iteration: previous=1, current=2 => result=3
// 2nd iteration: previous=3, current=3 => result=6
// 3rd iteration: previous=6, current=4 => result=10

every - 如果數組中的所有元素都在回調函數中傳遞測試,則返回true或false。

// Check if everybody has 18 years old of more.
var ages = [30, 43, 18, 5];  
ages.every(function(elem) {  
  return elem >= 18;
});

// Output: false

filter - 非常類似於除過濾器之外的每個過濾器返回一個數組,其中的元素返回true給定的函數。

// Finding the even numbers
[1,2,3,4,5,6].filter(function(elem){
  return (elem % 2 == 0)
});

// Output: [2,4,6]

希望這會有用。


沒有內置的能力可以突破forEach。要中斷執行,請使用Array#some以下內容:

[1,2,3].some(function(number) {
    return number === 1;
});

這是有效的,因為some只要以數組順序執行的任何回調返回true,就會返回true,從而使其餘的執行短路。原來的答案見陣原型some


有三種實現方式foreachjQuery如下。

var a = [3,2];

$(a).each(function(){console.log(this.valueOf())}); //Method 1
$.each(a, function(){console.log(this.valueOf())}); //Method 2
$.each($(a), function(){console.log(this.valueOf())}); //Method 3

你可以打電話給每個人這樣:

var a = ["car", "bus", "truck"]
a.forEach(function(item, index) {
    console.log("Index" + index);
    console.log("Element" + item);
})

element將具有從0到數組長度的每個索引的值。

輸出:

let Array = [1,3,2];

theArray.forEach((element)=>{ 
  // use the element of the array
  console.log(element) 
}

闡釋:

forEach是原型類。你也可以把它稱為theArray.prototype.forEach(...);

原型:https://hackernoon.com/prototypes-in-javascript-5bba2990e04bhttps://hackernoon.com/prototypes-in-javascript-5bba2990e04b

您還可以像這樣更改數組:

1    
3    
2

在JavaScript 中有幾種循環數組的方法,如下所示:

因為 - 這是最常見的一個。用於循環的完整代碼塊

var languages = ["JAVA", "JavaScript", "C#", "Python"];
var i, len, text;
for (i = 0, len = languages.length, text = ""; i < len; i++) {
    text += languages[i] + "<br>";
}
document.getElementById("example").innerHTML = text;
<p id="example"></p>

while - 循環而條件通過。它似乎是最快的循環

var text = "";
var i = 0;
while (i < 10) {
    text +=  i + ") something<br>";
    i++;
}
document.getElementById("example").innerHTML = text;
<p id="example"></p>

do / while - 在條件為真時循環遍歷代碼塊,將至少運行一次

var text = ""
var i = 0;
do {
    text += i + ") something <br>";
    i++;
}
while (i < 10);
document.getElementById("example").innerHTML = text;
<p id="example"></p>

功能循環 - ,forEachmapfilterreduce(他們通過循環功能,但如果你需要做的事情與你的陣列等使用

// For example, in this case we loop through the number and double them up using the map function
var numbers = [65, 44, 12, 4];
document.getElementById("example").innerHTML = numbers.map(function(num){return num * 2});
<p id="example"></p>

有關數組上函數編程的更多信息和示例,請參閱博客文章JavaScript中函數編程:map,filter和reduce


如果你不介意清空數組:

var x;

while(x = y.pop()){ 

    alert(x); //do something 

}

x將包含y的最後一個值,它將從數組中刪除。 你也可以使用shift()來提供和刪除y中的第一項。


一些C風格的語言使用foreach循環遍歷枚舉。 在JavaScript中,這是通過for..in循環結構完成的

var index,
    value;
for (index in obj) {
    value = obj[index];
}

有一個問題。 for..infor..in每個對象的可枚舉成員以及其原型上的成員。 要避免讀取通過對象原型繼承的值,只需檢查屬性是否屬於該對象:

for (i in obj) {
    if (obj.hasOwnProperty(i)) {
        //do stuff
    }
}

另外, ECMAScript 5已經向Array.prototype添加了一個forEach方法,該方法可用於使用calback枚舉數組(polyfill在文檔中,因此您仍然可以將它用於舊版瀏覽器):

arr.forEach(function (val, index, theArray) {
    //do stuff
});

值得注意的是,當回調返回false時, Array.prototype.forEach不會中斷。 jQueryUnderscore.jseach提供自己的變體,以提供可以短路的循環。


如果您正在使用jQuery庫,則可以使用jQuery.each

$.each(yourArray, function(index, value) {
  // do your stuff here
});

編輯:

根據問題,用戶想要javascript中的代碼而不是jquery,所以編輯是

var length = yourArray.length;   
for (var i = 0; i < length; i++) {
  // Do something with yourArray[i].
}

一個forEach實現( 參見jsFiddle ):

function forEach(list,callback) {
  var length = list.length;
  for (var n = 0; n < length; n++) {
    callback.call(list[n]);
  }
}

var myArray = ['hello','world'];

forEach(
  myArray,
  function(){
    alert(this); // do something
  }
);

我知道這是一個老帖子,已經有很多很棒的答案了。為了更完整一點,我想我會使用AngularJS投入另一個。當然,這只適用於你使用Angular的情況,顯然,無論如何我還是想把它放進去。

angular.forEach需要2個參數和一個可選的第三個參數。第一個參數是迭代的對象(數組),第二個參數是迭代器函數,可選的第三個參數是對像上下文(在循環內部基本上稱為'this'。

有不同的方法來使用forEach循環的角度。最簡單也可能最常用的是

var temp = [1, 2, 3];
angular.forEach(temp, function(item) {
    //item will be each element in the array
    //do something
});

另一種將項目從一個數組複製到另一個數組的方法是

var temp = [1, 2, 3];
var temp2 = [];
angular.forEach(temp, function(item) {
    this.push(item); //"this" refers to the array passed into the optional third parameter so, in this case, temp2.
}, temp2);

雖然,您不必這樣做,但您可以簡單地執行以下操作,它與上一個示例相同:

angular.forEach(temp, function(item) {
    temp2.push(item);
});

現在有使用該angular.forEach功能的優點和缺點,而不是內置的香草味for循環。

優點

  • 易讀性
  • 易寫性
  • 如果可用,angular.forEach將使用ES5 forEach循環。現在,我將獲得的利弊部分efficientcy,作為foreach循環是多少不是速度較慢的for循環。我作為專業人士提到這一點,因為保持一致和標準化是件好事。

考慮以下2個嵌套循環,這些循環完全相同。假設我們有2個對像數組,每個對象包含一個結果數組,每個結果都有一個Value屬性,它是一個字符串(或其他)。並且假設我們需要迭代每個結果,如果它們相等則執行一些操作:

angular.forEach(obj1.results, function(result1) {
    angular.forEach(obj2.results, function(result2) {
        if (result1.Value === result2.Value) {
            //do something
        }
    });
});

//exact same with a for loop
for (var i = 0; i < obj1.results.length; i++) {
    for (var j = 0; j < obj2.results.length; j++) {
        if (obj1.results[i].Value === obj2.results[j].Value) {
            //do something
        }
    }
}

誠然,這是一個非常簡單的假設的例子,但我已經寫了三重嵌入使用第二種方法循環,這是非常難讀,寫為這一問題。

缺點

  • 效率。angular.forEach和原生forEach,對於這個問題,都這麼多比正常情況下慢for循環....大約慢90% 。因此對於大型數據集,最好堅持原生for循環。
  • 沒有休息,繼續或返回支持。continue實際上是由“ accident ” 支持,繼續在angular.forEach你簡單地return;在函數中放置一個語句,angular.forEach(array, function(item) { if (someConditionIsTrue) return; });這將導致它繼續執行該迭代的函數。這也是由於本機forEach不支持中斷或繼續。

我相信還有其他各種優點和缺點,請隨意添加任何你認為合適的東西。我覺得,如果你需要效率的話,最重要的是,堅持使用原生for循環來滿足你的循環需求。但是,如果你的數據集較小,並且可以放棄一些效率以換取可讀性和可寫性,那麼無論如何都要拋棄angular.forEach那個壞孩子。


如果要循環遍歷數組,請使用標準的三部分for循環。

for (var i = 0; i < myArray.length; i++) {
    var arrayItem = myArray[i];
}

您可以通過緩存myArray.length或向後迭代來獲得一些性能優化。


向後循環

我認為反向循環值得一提:

for (var i = array.length; i--; ) {
     // process array[i]
}

好處:

  • 您不需要聲明臨時len變量,也不需要在每次迭代時與array.length進行比較,其中任何一個都可能是一個小時優化。
  • 以相反的順序從DOM中刪除兄弟姐妹通常更有效 。 (瀏覽器需要減少內部數組中元素的移動。)
  • 如果在循環時,在索引i處或之後修改數組 (例如,在array[i]刪除或插入項目),則前向循環將跳過向左移動到位置i的項目 ,或者重新處理i那個向右移動的物品。 在傳統的for循環中,您可以更新i以指向需要處理的下一個項目 - 1,但簡單地反轉迭代方向通常是一種更簡單更優雅的解決方案
  • 類似地,當修改或移除嵌套的 DOM元素時,反向處理可以避免錯誤 。 例如,在處理子節點之前,請考慮修改父節點的innerHTML。 到達子節點時,它將與DOM分離,在寫入父內部HTML時,已被新創建的子節點替換。
  • 鍵入和讀取的時間比其他一些可用選項 。 雖然它失去了forEach()和ES6的for ... of

缺點:

  • 它以相反的順序處理項目。 如果您從結果中構建新數組,或在屏幕上打印內容, 則輸出將相對於原始順序反轉
  • 為了保留他們的順序,重複地將兄弟姐妹插入DOM作為第一個孩子的效率較低 。 (瀏覽器將不得不改變方向。)要按順序有效地創建DOM節點,只需循環前進並正常追加(並使用“文檔片段”)。
  • 反向循環讓初級開發人員感到困惑 。 (你可以認為這是一個優勢,取決於你的前景。)

我應該經常使用它嗎?

一些開發人員默認使用reverse for循環,除非有充分的理由向前循環。

雖然性能提升通常微不足道,但它有點尖叫:

“只需對列表中的每個項目執行此操作,我不關心訂單!”

然而,在實踐中,這實際上並不是意圖的可靠指示,因為它與您關心訂單的情況無法區分,並且確實需要反向循環。 因此實際上需要另一個構造來準確表達“不關心”的意圖,這在大多數語言中目前都不可用,包括ECMAScript,但可以調用,例如, forEachUnordered()

如果順序無關緊要, 效率是一個問題(在遊戲或動畫引擎的最內層循環中),那麼使用反向循環作為你的首選模式是可以接受的。 請記住,在現有代碼看到反向循環並不一定意味著訂單無關緊要!

最好使用forEach()

一般來說,對於更高級別的代碼,其中清晰度和安全性是更大的問題,我建議使用Array::forEach作為默認模式:

  • 很清楚閱讀。
  • 它表明不會在塊中移位(這總是可能會隱藏在long forwhile循環中。)
  • 它為您提供了一個免費的閉包範圍。
  • 它減少了局部變量的洩漏以及外部變量的意外碰撞(和突變)。

然後,當你在代碼中看到反向for循環時,這是一個暗示它被推翻的原因很充分(可能是上述原因之一)。 並且看到傳統的前向循環可能表明可能發生轉移。

(如果對意圖的討論對你沒有意義,那麼你和你的代碼可能會受益於觀看Crockford關於編程風格和你的大腦的講座。)

它是如何工作的?

for (var i = 0; i < array.length; i++) { ... }   // Forwards

for (var i = array.length; i--; )    { ... }   // Reverse

您會注意到i--是中間子句(我們通常會看到比較),最後一個子句是空的(我們通常會看到i++ )。 這意味著我 - 也被用作繼續的條件 。 至關重要的是,它會每次迭代之前執行並檢查。

  • 它如何從array.length開始而不爆炸?

    因為i-- 每次迭代之前運行,所以在第一次迭代時我們實際上將訪問array.length - 1處的項目,這避免了Array-out-of-bounds undefined項目的任何問題。

  • 為什麼它不會在索引0之前停止迭代?

    當條件i--計算為假值(當它產生0時),循環將停止迭代。

    訣竅是,與--i不同,尾隨的i--運算符遞減i但在遞減之前產生值。 你的控制台可以證明:

    > var i = 5; [i, i--, i];

    [5, 5, 4]

    所以在最後一次迭代中, 之前是1並且i--表達式將其更改為0但實際上產生1 (真實),因此條件通過。 在下一次迭代中, i--i更改為-1但產生0 (falsey),導致執行立即退出循環的底部。

    在循環的傳統轉發中, i++++i是可以互換的(正如Douglas Crockford指出的那樣)。 但是在反向for循環中,因為我們的減量也是我們的條件表達式,所以如果我們想在索引0處理項目,我們必須堅持使用i--

瑣事

有些人喜歡在反面畫一個小箭頭,然後以眨眼結束:

for (var i = array.length; i --> 0 ;) {

積分轉到WYL,向我展示反向循環的好處和恐怖。







iteration