Почему 'for (var item in list)' с массивами считается плохой практикой в ​​JavaScript? - PullRequest
70 голосов
/ 15 февраля 2010

Учитывая простой нумерованный индексированный массив:

var list = ['Foo', 'Bar', 'Baz'];

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

for(var item in list) { ... }

... почти наверняка кто-то считает, что это плохая практика, и предлагает альтернативный подход:

var count = list.length;

for(var i = 0; i < count; i++) {
    var item = list[i];
    ...
}

В чем причина не использовать более простую версию выше и использовать вместо нее второй пример?

Ответы [ 5 ]

84 голосов
/ 15 февраля 2010

Во-первых, порядок цикла не определен для цикла for...in, поэтому нет гарантии, что свойства будут повторяться в нужном вам порядке.

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

Array.prototype.remove = function(val) {
    // Irrelevant implementation details
};

var a = ["a", "b", "c"];

for (var i in a) {
    console.log(i);
}

// Logs 0, 1, 2, "remove" (though not necessarily in that order)
17 голосов
/ 15 февраля 2010

Скорость?

Петля

for(..;..;..) оказалась в 36 раз быстрее, чем for .. in , когда я ее здесь тестировал.

Ссылка предоставлена ​​таким SO ответом

1 голос
/ 15 февраля 2010

Если вы используете для / in таким образом, item перечисляет через строковые значения "0", "1", ..., а не фактические объекты в списке. Таким образом, «элемент» в первом фрагменте больше похож на i во втором фрагменте, а не на item. Кроме того, строковые значения перечисляются там, где вы ожидаете чисел. И вы попадаете в беду, когда вы вносите свойства в список, например array.ID = "a123", поскольку они также будут перечислены.

Но с учетом этих недостатков я все еще думаю, что синтаксис очень полезен, если ваша команда знает, что он делает.

0 голосов
/ 29 сентября 2018

for ... in ... не возвращает элементы списка, а перечисляет свойства массива.

По этой причине он не может служить заменой for (i=0; i<arr.length; i++) петли.

Подходящей альтернативой является конструкция for ... of .... Перечисляет значения повторяемого объекта, такого как массив. Подробнее об этом можно прочитать в MDN Web Docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of

Он поддерживается соответствующими современными браузерами (Internet Explorer не считается, его заменяет Microsoft Edge). Если вы можете позволить себе не поддерживать старые браузеры, это, вероятно, путь. Вы можете проверить удобную таблицу поддержки браузера в конце вышеупомянутой страницы MDN, чтобы увидеть, какие версии браузера на самом деле допускают использование for ... of ....

0 голосов
/ 15 февраля 2010

Добавьте list.foo = bar; и попробуйте использовать простой for. Если вы не используете некоторые библиотеки (например, prototypeJs) и не добавляете какие-либо новые свойства в объект массива - вы можете использовать простой оператор for.

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