JavaScript для... в vs для

Считаете ли вы, что существует большая разница для... внутри и для циклов? Какую "для" вы предпочитаете использовать и почему?

Скажем, у нас есть массив ассоциативных массивов:

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

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

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

и

for (var i in myArray)

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

Ответы

Ответ 1

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

Массив повторяется с помощью:

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

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

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

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

Ответ 2

Дуглас Крокфорд рекомендует в JavaScript: Хорошие части (стр. 24), чтобы избежать использования оператора for in.

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

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

for (var name in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, name)) {
        // DO STUFF
    }
}

Ответ 3

FYI - пользователи jQuery


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

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

Пример:

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

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


Ответ 4

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

Например:

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

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

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

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

Ответ 5

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

Ответ 6

Обновленный ответ на 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.

Ответ 7

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

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

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

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

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

Ответ 8

Использование 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]);
});

Ответ 9

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

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.
}

Ответ 10

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

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

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

Ответ 11

Я бы использовал различные методы, основанные на том, как я хотел бы ссылаться на элементы.

Использовать foreach, если вам нужен только текущий элемент.

Используйте, если вам нужен индекс для выполнения относительных сравнений. (Например, как это соотносится с предыдущим/следующим пунктом?)

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

Ответ 12

С помощью for (var я в myArray) вы можете также перебирать объекты, я буду содержать имя ключа, и вы можете получить доступ к свойству через myArray [i]. Кроме того, любые методы, которые вы добавили в объект, также будут включены в цикл, т.е. Если вы используете какую-либо внешнюю структуру, например jQuery или прототип, или если вы добавляете методы для прототипов объектов напрямую, в какой-то момент я укажу на эти методы.

Ответ 13

Остерегайтесь!

Если у вас несколько тегов script и ваш поиск информации в атрибутах тегов, например, вы должны использовать свойство .length с циклом for, потому что это не простой массив, а объект HTMLCollection.

https://developer.mozilla.org/en/DOM/HTMLCollection

Если вы используете оператор foreach для (var я в вашемList), он вернет proterties и методы HTMLCollection в большинстве браузеров!

var scriptTags = document.getElementsByTagName("script");

for(var i = 0; i < scriptTags.length; i++)
alert(i); // Will print all your elements index (you can get src attribute value using scriptTags[i].attributes[0].value)

for(var i in scriptTags)
alert(i); // Will print "length", "item" and "namedItem" in addition to your elements!

Даже если getElementsByTagName должен вернуть NodeList, большинство браузеров возвращают HTMLCollection: https://developer.mozilla.org/en/DOM/document.getElementsByTagName

Ответ 14

Для циклов в массивах Массивы не совместимы с Prototype. Если вы считаете, что вам может понадобиться использовать эту библиотеку в будущем, имеет смысл придерживаться циклов.

http://www.prototypejs.org/api/array

Ответ 15

Я видел проблемы с "для каждого" с использованием объектов и прототипов и массивов

Я понимаю, что для каждого есть свойства объектов и массивы NOT

Ответ 16

Если вы действительно хотите ускорить свой код, что с этим связано?

for( var i=0,j=null; j=array[i++]; foo(j) );

это своего рода наличие логики while в инструкции for и она менее избыточна. Также firefox имеет Array.forEach и Array.filter

Ответ 17

Более короткий и лучший код в соответствии с jsperf

keys  = Object.keys(obj);
for (var i = keys.length; i--;){
   value = obj[keys[i]];// or other action
}

Ответ 18

Используйте цикл Array(). forEach, чтобы воспользоваться parallelism

Ответ 19

for (;;) для Массивы: [20,55,33]

для.. в для объектов: {x: 20, y: 55: z: 33}

Ответ 20

Будьте осторожны! Я использую Chrome 22.0 в Mac OS, и у меня возникают проблемы с каждым синтаксисом.

Я не знаю, является ли это проблемой браузера, проблемой javascript или некоторой ошибкой в ​​коде, но это ОЧЕНЬ странно. Вне объекта он отлично работает.

var MyTest = {
    a:string = "a",
    b:string = "b"
};

myfunction = function(dicts) {
    for (var dict in dicts) {
        alert(dict);
        alert(typeof dict); // print 'string' (incorrect)
    }

    for (var i = 0; i < dicts.length; i++) {
        alert(dicts[i]);
        alert(typeof dicts[i]); // print 'object' (correct, it must be {abc: "xyz"})
    }
};

MyObj = function() {
    this.aaa = function() {
        myfunction([MyTest]);
    };
};
new MyObj().aaa(); // This does not work

myfunction([MyTest]); // This works

Ответ 21

Между ними существует важное различие. Функция in-in выполняет итерацию по свойствам объекта, поэтому, когда случай представляет собой массив, он будет не только перебирать элементы, но также и над функцией "удалить", которую он имеет.

for (var i = 0; i < myArray.length; i++) { 
    console.log(i) 
}

//Output
0
1

for (var i in myArray) { 
    console.log(i) 
} 

// Output
0 
1 
remove

Вы можете использовать for-in с if(myArray.hasOwnProperty(i)). Тем не менее, при повторении массивов я всегда предпочитаю избегать этого и просто использовать инструкцию for (;;).

Ответ 22

Хотя они оба очень похожи, есть незначительная разница:

var array = ["a", "b", "c"];
array["abc"] = 123;
console.log("Standard for loop:");
for (var index = 0; index < array.length; index++)
{
  console.log(" array[" + index + "] = " + array[index]); //Standard for loop
}

в этом случае вывод:

СТАНДАРТ ДЛЯ ЛОП:

ARRAY [0] = A

ARRAY [1] = B

ARRAY [2] = C

console.log("For-in loop:");
for (var key in array)
{
  console.log(" array[" + key + "] = " + array[key]); //For-in loop output
}

в то время как в этом случае выход:

FOR-IN LOOP:

ARRAY [1] = B

ARRAY [2] = C

ARRAY [10] = D

ARRAY [ABC] = 123

Ответ 23

Оператор for in позволяет прокручивать имена всех свойств объекта. К сожалению, он также проходит через все элементы, которые были унаследованы через цепочку прототипов. Это имеет плохой побочный эффект от обслуживания функций метода, когда интерес заключается в элементах данных.