JavaScript для ... в сравнении с - PullRequest
       42

JavaScript для ... в сравнении с

449 голосов
/ 28 октября 2008

Как вы думаете, есть большая разница в циклах for ... in и for? Какое «для» вы предпочитаете использовать и почему?

Допустим, у нас есть массив ассоциативных массивов:

var myArray = [{'key': 'value'}, {'key': 'value1'}];

Итак, мы можем повторить:

for (var i = 0; i < myArray.length; i++)

И

for (var i in myArray)

Я не вижу большой разницы. Есть ли проблемы с производительностью?

Ответы [ 23 ]

543 голосов
/ 28 октября 2008

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

Массив повторяется с использованием:

for (var i = 0; i < a.length; i++)
   //do stuff with a[i]

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

for (var key in o)
  //do stuff with o[key]

Если у вас нет причин для разрушения земли, придерживайтесь установленной схемы использования.

160 голосов
/ 28 октября 2008

Дуглас Крокфорд рекомендует в JavaScript: The Good Parts (стр. 24) избегать использования оператора for in.

Если вы используете for in для зацикливания имен свойств в объекте, результаты не упорядочиваются. Хуже: вы можете получить неожиданные результаты; в него входят члены, унаследованные от цепочки прототипов, и имена методов.

Все, кроме свойств, может быть отфильтровано с помощью .hasOwnProperty. Этот пример кода делает то, что вы, вероятно, хотели изначально:

for (var name in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, name)) {
        // DO STUFF
    }
}
62 голосов
/ 04 августа 2009

FYI - jQuery Users


Метод jQuery each(callback) по умолчанию использует цикл for( ; ; ) и будет использовать for( in ) только , если длина undefined.

Поэтому я бы сказал, что при использовании этой функции можно принять правильный порядок.

Пример

$(['a','b','c']).each(function() {
    alert(this);
});
//Outputs "a" then "b" then "c"

Недостатком использования этого является то, что если вы выполняете какую-то логику без пользовательского интерфейса, ваши функции будут менее переносимы к другим средам. Функция each(), вероятно, лучше всего зарезервирована для использования с селекторами jQuery, и в противном случае рекомендуется for( ; ; ).


29 голосов
/ 28 октября 2008

существуют различия в производительности в зависимости от того, какой цикл вы используете и в каком браузере.

Например:

for (var i = myArray.length-1; i >= 0; i--)

почти вдвое быстрее в некоторых браузерах, чем:

for (var i = 0; i < myArray.length; i++)

Однако, если ваши массивы ОГРОМНЫ или вы не зацикливаете их постоянно, все достаточно быстро. Я серьезно сомневаюсь, что зацикливание массивов является узким местом в вашем проекте (или для любого другого проекта в этом отношении)

26 голосов
/ 22 июня 2011

Обратите внимание, что собственный метод Array.forEach теперь широко поддерживается .

24 голосов
/ 12 января 2012

Обновленный ответ за 2012 год текущая версия всех основных браузеров - Chrome, Firefox, IE9, Safari и Opera поддерживают собственный массив ES5.forEach.

Если у вас нет причин поддерживать нативную поддержку IE8 (учитывая, что этим пользователям могут быть предоставлены рамки ES5-shim или Chrome, которые обеспечат надлежащую среду JS), проще использовать правильный синтаксис языка:

myArray.forEach(function(item, index) {
    console.log(item, index);
});

Полная документация для array.forEach () находится в MDN.

14 голосов
/ 28 октября 2008

Я полагаю, что вы должны выбрать метод итерации в соответствии с вашими потребностями. Я бы посоветовал вам на самом деле не когда-либо проходить через нативную Array со структурой for in. Это намного медленнее и , как указывал Чейз Сейберт недавно, несовместимо с платформой Prototype.

Существует отличный тест для различных стилей зацикливания, на который вы обязательно должны обратить внимание, если работаете с JavaScript . Не выполняйте раннюю оптимизацию, но вы должны держать эту штуку где-то в затылке.

Я бы использовал for in, чтобы получить все свойства объекта, что особенно полезно при отладке ваших сценариев. Например, мне нравится иметь эту строку под рукой, когда я исследую незнакомый объект:

l = ''; for (m in obj) { l += m + ' => ' + obj[m] + '\n' } console.log(l);

Он выгружает содержимое всего объекта (вместе с телами методов) в мой журнал Firebug. Очень удобно.

14 голосов
/ 12 марта 2012

Использование forEach для пропуска цепочки прототипов

Просто быстрое дополнение к @ ответу nailer выше , использование forEach с Object.keys означает, что вы можете избежать итерации по цепочке прототипов без использования hasOwnProperty.

var Base = function () {
    this.coming = "hey";
};

var Sub = function () {
    this.leaving = "bye";
};

Sub.prototype = new Base();
var tst = new Sub();

for (var i in tst) {
    console.log(tst.hasOwnProperty(i) + i + tst[i]);
}

Object.keys(tst).forEach(function (val) {
    console.log(val + tst[val]);
});
13 голосов
/ 22 июня 2011

Они не совпадают, когда массив разрежен.

var array = [0, 1, 2, , , 5];

for (var k in array) {
  // Not guaranteed by the language spec to iterate in order.
  alert(k);  // Outputs 0, 1, 2, 5.
  // Behavior when loop body adds to the array is unclear.
}

for (var i = 0; i < array.length; ++i) {
  // Iterates in order.
  // i is a number, not a string.
  alert(i);  // Outputs 0, 1, 2, 3, 4, 5
  // Behavior when loop body modifies array is clearer.
}
7 голосов
/ 24 июля 2009

вот что я сделал.

function foreach(o, f) {
 for(var i = 0; i < o.length; i++) { // simple for loop
  f(o[i], i); // execute a function and make the obj, objIndex available
 }
}

это то, как вы будете использовать его
это будет работать с массивами и объектами (такими как список элементов HTML)

foreach(o, function(obj, i) { // for each obj in o
  alert(obj); // obj
  alert(i); // obj index
  /*
    say if you were dealing with an html element may be you have a collection of divs
  */
  if(typeof obj == 'object') { 
   obj.style.marginLeft = '20px';
  }
});

Я только что сделал это, поэтому я открыт для предложений:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...