Использование a для каждого цикла в пустом массиве в JavaScript

Я обнаружил, что я не могу использовать a для каждого цикла в пустом массиве в javascript. Может ли кто-нибудь объяснить мне, почему это так?

Я инициализировал массив в javascript следующим образом:

var arr = new Array(10);

когда я использую для каждого цикла в массиве, ничего не происходит:

arr.forEach(function(i) {
    i = 0;
});

результат по-прежнему представляет собой массив неопределенных значений:

arr = [ , , , , , , , , , ];

Я думаю, что, возможно, поскольку каждый элемент в массиве не определен, он даже не выполняет forEach. Я бы подумал, что он все равно будет перебирать неопределенные предметы. Может ли кто-нибудь объяснить, почему это происходит? Этот вопрос не спрашивает, как наиболее эффективно заполнить массив нулями, он задает детали о взаимодействии a для каждого цикла и пустого массива.

Ответ 1

Ты на полпути!

Я думаю, что, возможно, поскольку каждый элемент в массиве не определен, он даже не выполняет forEach.

Array.prototype.forEach не посещает индексы, которые были удалены или удалены; это процесс называется эллипсом. Таким образом, он выполняется, но пропускает каждый элемент.

Из MDN: Screenshot from MDN regarding forEach

Ответ 2

Вы можете использовать forEach, как и вы, если вы измените инициализацию массива:

var arr = Array.apply(null, Array(10))

И тогда вы можете сделать foreach как:

arr.forEach(function(el, index) {
    arr[index] = 0;
});

Результат:

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Ответ 3

.forEach запускает вашу функцию для каждого элемента массива. Установка значения i ничего не делает, это не ссылка.

Просто используйте нормальный for цикла:

for(var i = 0; i < arr.length; i++){
    arr[i] = 0;
}

Или вместо создания new Array(10) вы можете просто сделать:

var arr = [];
for(var i = 0; i < 10; i++){
    arr[i] = 0;
}

Ответ 5

Надеюсь, кто-то может исправить меня, если я ошибаюсь в этом

Внутри исходного кода V8 array.js: 1042 я нашел следующее:

for (var i = 0; i < length; i++) {
      if (i in array) {
        var element = array[i];
        f(element, i, array);
      }
      //...

Важным битом является проверка состояния с помощью оператора "in", чтобы определить, следует ли выполнять аргумент функции, переданный в forEach. Оператор in проверяет наличие свойств внутри объекта.

Теперь массив JS - просто причудливый объект с пронумерованными свойствами. Т.е.

var array = [undefined,undefined,undefined];
Object.keys(array); // ["0", "1", "2"]

Другой способ мышления об этом массиве - думать об этом как о таком объекте

{
  "0": undefined,
  "1": undefined,
  "2": undefined
}

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

var array2 = new Array(3);
Object.keys(array2); // []

Вот почему вы получите следующий результат:

var array = [undefined,undefined,undefined];
var array2 = new Array(3);

array.forEach(function(){console.log('foo')}); //will print foo three times
array2.forEach(function(){console.log('bar')}); //will print nothing

Ответ 6

Контроль того, что "устранено"

Как уже упоминалось, ключевым присутствием является то, что определяет, если forEach попадает, а длина просто определяет диапазон ключей для проверки.

Еще одна интересная перспектива в этом заключается в том, что вы можете контролировать то, что видно для forEach и других итерационных методов, используя прокси с ловушкой.

здесь мы фильтруем нечетные знаки.

let arr = ['zero', 'one', 'two', 'four']
arr.length = 6

let arrProxy = new Proxy(arr, { has(arr, k){ return k%2===0 } })

arrProxy.forEach( val => { console.log(val) })
//zero
//two
//undefined

Такая стратегия также позволяет вам перейти к другим видам поведения,

если вместо k%2===0 вас было

  • true вы бы ударили по всему пустому пространству.
  • k != undefined позволяет вам перебирать только определенные значения.
  • k in arr возвращает вас туда, где вы начали.

конечно, вы должны использовать фильтр в большинстве ситуаций, это всего лишь демонстрация.