Страницы

Поиск по вопросам

воскресенье, 8 декабря 2019 г.

В чём опасность использования for .. in для объекта или массива?

#javascript #javascript_faq


В чём опасность использования for .. in для объекта или массива?
    


Ответы

Ответ 1



Как написано в mdn Проход по массиву и for...in Замечание: for...in не следует использовать для Array, где важен порядок индексов. Индексы массива - перечисляемые свойства с целочисленными именами, а в остальном аналогичны свойствам объектов. Нет гарантии, что for...in будет возвращать индексы в нужном порядке и вернёт все перечисляемые свойства, включая имеющие не целочисленные имена и наследуемые. Поэтому порядок прохода зависит от реализации, проход по массиву может не произойти в правильном порядке. Следовательно лучше с числовыми индексами использовать циклы for, Array.prototype.forEach() или for...of, когда проходим по массивам, где важен порядок доступа к свойствам.

Ответ 2



Для объекта: Перебираются все ключи, в том числе унаследованные: var obj = {a: 9}; Object.prototype.myAwfulThing = 8; for (var key in obj) { console.log(key); } При этом унаследованное свойство может быть добавлено какой-то библиотекой. Поэтому рекомендуется делать проверку на наличие свойства в самом объекте: var obj = {a: 9}; Object.prototype.myAwfulThing = 8; for (var key in obj) { if (obj.hasOwnProperty(key)) { console.log(key); } } Даже если ты на 100% уверен, что унаследованных свойств нет, библиотеками никакими не пользуешься и всё замечательно работает, браузер-то об этом не знает. Браузер оптимизирует только случай, когда есть проверка на hasOwnProperty. Что-то этот пункт не захотел подтверждаться экспериментально. Для массива: Будут перебираться не только индексы, но и другие свойства. Если вместо массива окажется массивоподобный объект, то может попасться свойство length. Если подключены полифилы для массивов (что весьма вероятно), в браузерах, не умеющих делать скрытые свойства, в перебор попадут все эти функции. Перебираются только индексы, которые есть в массиве. Если элемент массива удалялся через delete, либо добавление в массив происходило по индексу после его конца, то отсутствующие индексы будут пропущены. Но порядок перебираемых индексов будет верным. var a = [undefined, , 4]; a[7] = undefined; for (var i in a) { // 0 2 7 console.log(i); } Перебор массива через for in по производительности уступает нормальному циклу в десятки раз. ES6 Для перебора элементов массива (значений, не индексов!) ES6 вводит цикл for of: var a = [undefined, , 4]; a[7] = undefined; for (var x of a) { console.log(x); } 2 раза выводится undefined, затем 4 и ещё 5 раз undefined.

Комментариев нет:

Отправить комментарий