w3school - w3c javascript foreach




For-each在JavaScript中的數組? (19)

向後循環

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

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,向我展示反向循環的好處和恐怖。

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

我以為它是這樣的:

forEach(instance in theArray)

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


摘要:

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

  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);
}


使用循環與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);
});


從ES6開始:

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

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

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


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]

希望這會有用。


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);
});

一個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
  }
);

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

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

如果您正在使用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].
}

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

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

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


這是NON稀疏列表的迭代器,其中索引從0開始,這是處理document.getElementsByTagName或document.querySelectorAll時的典型場景。

function each( fn, data ) {

    if(typeof fn == 'string')
        eval('fn = function(data, i){' + fn + '}');

    for(var i=0, L=this.length; i < L; i++) 
        fn.call( this[i], data, i );   

    return this;
}

Array.prototype.each = each;  

用法示例:

示例#1

var arr = [];
[1, 2, 3].each( function(a){ a.push( this * this}, arr);
arr = [1, 4, 9]

例#2

each.call(document.getElementsByTagName('p'), "this.className = data;",'blue');

每個p標籤都有 class="blue"

例#3

each.call(document.getElementsByTagName('p'), 
    "if( i % 2 == 0) this.className = data;",
    'red'
);

每個其他p標籤獲得class="red">

例#4

each.call(document.querySelectorAll('p.blue'), 
    function(newClass, i) {
        if( i < 20 )
            this.className = newClass;
    }, 'green'
);

最後,前20個藍色p標籤變為綠色

使用字符串作為函數時的注意事項:該函數是在上下文中創建的,只應在您確定變量作用域的情況下使用。否則,最好傳遞範圍更直觀的函數。



可能for(i = 0; i < array.length; i++)循環不是最好的選擇。為什麼? 如果你有這個:

var array = new Array();
array[1] = "Hello";
array[7] = "World";
array[11] = "!";

該方法將調用從array[0]array[2]。首先,這將首先引用你甚至沒有的變量,第二個你不會在數組中有變量,第三個會使代碼更大膽。看這裡,這是我使用的:

for(var i in array){
    var el = array[i];
    //If you want 'i' to be INT just put parseInt(i)
    //Do something with el
}

如果你想讓它成為一個函數,你可以這樣做:

function foreach(array, call){
    for(var i in array){
        call(array[i]);
    }
}

如果你想打破,更多的邏輯:

function foreach(array, call){
    for(var i in array){
        if(call(array[i]) == false){
            break;
        }
    }
}

例:

foreach(array, function(el){
    if(el != "!"){
        console.log(el);
    } else {
        console.log(el+"!!");
    }
});

它返回:

//Hello
//World
//!!!

在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


如果你有一個龐大的陣列,你應該用它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閱讀更多信息。


我知道這是一個老帖子,已經有很多很棒的答案了。為了更完整一點,我想我會使用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那個壞孩子。


有三種實現方式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

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

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

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


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






iteration