JavaScript-нюансы myArray.по каждому элементу против для петли


Я видел много вопросов, которые предлагают использовать:

for (var i = 0; i < myArray.length; i++){ /* ... */ }

вместо:

for (var i in myArray){ /* ... */ }

для массивов, из-за несогласованных итерации (см. здесь).


однако, я не могу найти ничего, что, кажется, предпочитает объектно-ориентированный цикл:

myArray.forEach(function(item, index){ /* ... */ });

что кажется мне более интуитивным.

для моего текущего проекта важна совместимость IE8, и я рассматриваю возможность использования полифилл Mozilla, однако я не уверен на 100%, как это будет работать.

  • существуют ли какие-либо различия между стандартным циклом for (первый пример выше) и массивом.прототип.реализация forEach современными браузерами?
  • есть ли разница между современными реализациями браузера и реализацией Mozilla, связанной с выше (с особым учетом IE8)?
  • производительность-это не столько проблема, сколько согласованность, с которой повторяются свойства свыше.
3 88

3 ответа:

самая существенная разница между for петли и forEach метод заключается в том, что с первым вы можете break выход из цикла. Вы можете имитировать continue просто возвращаясь из функции, переданной в forEach, но нет никакого способа, чтобы остановить зацикливание.

кроме того, они эффективно выполняют одну и ту же функциональность. Еще одно незначительное различие связано с областью действия индекса (и всех содержащих переменных) в цикле for, из-за переменной подъемный.

// 'i' is scoped to the containing function
for (var i = 0; i < arr.length; i++) { ... }

// 'i' is scoped to the internal function
arr.forEach(function (el, i) { ... });

однако, я считаю, что forEach гораздо более выразительно-он представляет ваше намерение перебирать каждый элемент массива, и он предоставляет вам ссылку на элемент, а не только индекс. В целом, это в основном сводится к личному вкусу, но если вы можете использовать forEach, Я бы рекомендовал использовать его.


есть еще несколько существенных различий между двумя версиями, в частности в отношении производительности. На самом деле, простой для цикла выполняет значительно лучше, чем forEach метод, как показала этот тест jsperf.

нужна ли вам такая производительность, зависит от вас, и в большинстве случаев я бы предпочел выразительность скорости. Эта разница в скорости, вероятно, связана с незначительными семантическими различиями между базовым циклом и методом при работе с разреженными массивами, как отмечено в ответ.

Если вам не нужны поведение forEach и/или вам нужно вырваться из цикла рано, вы можете использовать Lo-Dash в _.each в качестве альтернативы, которая также будет работать кросс-браузер. Если вы используете jQuery, он также предоставляет аналогичный $.each, просто обратите внимание на различия в аргументах, передаваемых функции обратного вызова в каждом варианте.

(как forEach полифилл, он должен работать в старых браузерах без проблем, если вы решите пойти по этому пути.)

Вы можете использовать свою пользовательскую функцию foreach, которая будет работать намного лучше, чем массив.по каждому элементу

вы должны добавить это один раз в свой код. Это добавит новую функцию в массив.

function foreach(fn) {
    var arr = this;
    var len = arr.length;
    for(var i=0; i<len; ++i) {
        fn(arr[i], i);
    }
}

Object.defineProperty(Array.prototype, 'customForEach', {
    enumerable: false,
    value: foreach
});

затем вы можете использовать его в любом месте, как массив.по каждому элементу

[1,2,3].customForEach(function(val, i){

});

единственная разница это в 3 раза быстрее. https://jsperf.com/native-arr-foreach-vs-custom-foreach

обновление: в новой версии Chrome производительность .еогеасп() была усовершенствована. Тем не менее, решение может дать дополнительную производительность в других браузерах.

JSPerf

некоторые разработчики (например, Кайл Симпсон) предлагают использовать .forEach, чтобы указать, что массив будет иметь побочный эффект и .map для чистых функций. for петли в этом уравнении, то, на мой взгляд, вписываются в это уравнение как решение общего назначения, которое легче общаться, поскольку оно поддерживается во множестве языков esp, когда # итераций предварительно вычисляется.