Почему эта карта JavaScript НЕ является бесконечным циклом? - PullRequest
9 голосов
/ 11 июня 2019

Я изучаю JavaScript.Я написал этот код для изучения функции карты.Но затем я запутался в том, почему это не отображается на нем непрерывно, так как с каждой последовательностью карты новый элемент помещается в массив.Разве это не должно продолжать выдвигать новые элементы, поскольку это сопоставляется? Почему функция карты запускается только для исходных трех элементов, а не для новых вставленных?

Я попытался отладить ее в среде узла, а переменная arr помещается в закрытие .Я знаю, что за закрытие, но я не могу понять, что здесь происходит.

let array = [1, 2, 3];

array.map((element) => {
  array.push(10);
  console.log(element);
});

Я ожидаю, что выходной сигнал должен быть 1,2,3,10,10,10,10,10,10,10,10......10

Но фактический выходной сигнал составляет всего 1,2,3.

Ответы [ 3 ]

10 голосов
/ 11 июня 2019

Цитировать из MDN:

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

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map#Description

Итак, он ведет себя так, потому что так оно и задумано. И он спроектирован таким образом, среди прочего, чтобы предотвратить бесконечные циклы!

map - это функция из мира функционального программирования, где неизменность является важным принципом. Согласно этому принципу, если вы вызовете map на входе (а другие переменные не изменятся), вы всегда получите точно тот же результат. Разрешение модификации ввода нарушает неизменность.

7 голосов
/ 11 июня 2019

Поскольку не изменяет массив (см. Array​.prototype​.map()) .

Вместо этого он возвращает новый массив с результатами вызова предоставленной функции для каждого элемента в вызывающем массиве.

В следующем фрагменте мутирует array три раза (один раз на элемент в исходном массиве), а не саму функцию map.

let newArray = array.map((element) => {
    array.push(10); // <-- here you mutate the array
    console.log(element);
});

Важная цитата из упомянутой документации (и ключевой момент здесь):

Диапазон элементов, обрабатываемых картой, устанавливается перед первым вызов обратного вызова . Элементы, которые добавляются в массив после начала вызова на карту не будет посещен обратный вызов.


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

let array = [1,2,3];
let newArray = array.map(element => element + 10);  // sum 10 to every element

console.log('original: ', array); // original:  [1,2,3]
console.log('new one: ', newArray) // new one:  [11,12,13]

Последняя мысль (также из документации), взяв в качестве ссылки код, который вы разместили:

Поскольку map создает новый массив, использование его, когда вы не используете возвращенный массив, является анти-паттерном; используйте вместо этого forEach или for-of.

Знаки, которые вы не должны использовать карту:

  • A) Вы не используете возвращаемый массив и / или

  • B) Вы не возвращаете значение из обратного вызова.

4 голосов
/ 11 июня 2019

Почему именно так, как видно на MDN:

var new_array = arr.map(function callback(currentValue[, index[, array]]){}

Диапазон элементов, обрабатываемых картой, устанавливается перед первым вызовом обратного вызова. Элементы, которые добавляются в массив после начала вызова карты, не будут посещаться обратным вызовом.

(Спасибо за сообщение Джо из MDN за эту цитату.)

Как только карта вызывается, она принимает массив в этот момент в качестве параметра; как только он пройден, любые изменения не имеют отношения к самой предыдущей переменной.

См. Ниже:

let array = [1, 2, 3];

array.map((element) => {
  array.push(10);
  console.log(element);
});

console.log(array)
...