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

229
24 июля 2017, 16:29

В чём опасность использования 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
JavaScript самая длинная комбинация из k строк идущих подряд.

JavaScript самая длинная комбинация из k строк идущих подряд.

Всем доброго времени суток, есть массив состоящий из строк к примеру

217
Новый поток для отправки пинга сокету

Новый поток для отправки пинга сокету

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

189
Сохранение данных в БД пользователя и гостя при создании поста

Сохранение данных в БД пользователя и гостя при создании поста

Гостевая книга на сайте где можно оставить пост как гостю так и зарегпользователю

228
Как защитить сайт от перебора паролей?

Как защитить сайт от перебора паролей?

Всем здарова, срочно нужна помощьУ меня реализована простая авторизация, в бд хранится e-mail, и хэш пароля

275