Почему' for(var item in list) ' с массивами считается плохой практикой в JavaScript?


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

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 65

5 ответов:

во-первых, порядок цикла не определен для 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)

скорость?

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

ссылка любезно это так ответ

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

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

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

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 ... использование.