Как довольно четко описано в документации MDN , метод .forEach()
определяет элементы, которые будут задействованы в итерации до ее запуска.
Если элементы добавляются в массив, они не будут включены в итерацию. Если элементы будут удалены, последующие элементы будут пропущены. По сути, для выбора каждого элемента используется внутренний индекс, поэтому, если массив становится короче, этот индекс не может быть соответствующим образом скорректирован.
Кроме того, ваш код написан так, что обратный вызов .forEach()
игнорирует его аргументы. ,Он всегда просто удаляет первый элемент массива fruits
. Таким образом, на первой итерации вы получаете «Apple», а массив теперь состоит всего из трех элементов. Следующим итерированным элементом будет «Mango», а не «Banana», но поскольку код не обращает внимания на item
, вы получаете новый первый элемент исходного массива. После этого в массиве есть только два элемента, поэтому итерация заканчивается.
Вы можете увидеть точно такой же эффект с этим кодом, который, возможно, более понятен, поскольку механизм видим:
const fruits = ['Apple', 'Banana', 'Mango', 'Pomegranate']
const fruitsList = []
for (let index = 0, len = fruits.length; index < len; index++) {
if (index in fruits) {
let fruit = fruits.splice(0,1)
fruitsList.push(fruit)
}
}
Тест if
в этом цикле иллюстрирует важное поведение .forEach()
: он пропускает пустые индексы массива (то есть, которые никогда не были инициализированы значением). Вызовы .slice()
удаляют элемент из fruits
, поэтому после первых двух итераций он даже не будет пытаться выполнить больше .slice()
вызовов, потому что индексы 2 и 3 будут пустыми.
правильный способ сделать это, если бы это был реальный код, был бы
const fruits = ['Apple', 'Banana', 'Mango', 'Pomegranate']
const fruitsList = fruits.map(function(fruit) {
return [fruit];
});
fruits = []; // if you really want to empty it out
(а функция =>
была бы еще более краткой).