Использование 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:
Ответ 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;
}
Ответ 4
На основе ответа Фариса Засины один подход.
var zeros = Array.apply(null, Array(10)).map(function(){return 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
возвращает вас туда, где вы начали.
конечно, вы должны использовать фильтр в большинстве ситуаций, это всего лишь демонстрация.