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

160
29 октября 2018, 14:20

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

Answer 1
Для объекта:
  • Перебираются все ключи, в том числе унаследованные:

    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.

Answer 2

Как написано в mdn

Проход по массиву и for...in

Замечание: for...in не следует использовать для Array, где важен порядок индексов.

Индексы массива - перечисляемые свойства с целочисленными именами, а в остальном аналогичны свойствам объектов. Нет гарантии, что for...in будет возвращать индексы в нужном порядке и вернёт все перечисляемые свойства, включая имеющие не целочисленные имена и наследуемые.

Поэтому порядок прохода зависит от реализации, проход по массиву может не произойти в правильном порядке. Следовательно лучше с числовыми индексами использовать циклы for, Array.prototype.forEach() или for...of, когда проходим по массивам, где важен порядок доступа к свойствам.

READ ALSO
Как сделать сортировку div-ов в JavaScript?

Как сделать сортировку div-ов в JavaScript?

Нужно сортировать не вертикально а горизонтально!

232
Как считать значение параметра тега HTML в js?

Как считать значение параметра тега HTML в js?

как присвоить переменной значение параметра style через его класс?

154
Количество повторений в массиве через reduce

Количество повторений в массиве через reduce

Уже видел ответы на вопрос подсчёта повторений в массиве, но не понятно, что конкретно делает 2строка acc[el] = (acc[el] || 0) + 1;

177
Почему я получаю ошибку 1045 “Access denied for user”?

Почему я получаю ошибку 1045 “Access denied for user”?

Моя проблема заключается в (1045, "Access denied for user ')Вот код на python

166