Карта JavaScript: Почему это не работает?
Я пытался создать некоторые случайные данные, используя карту. К моему удивлению, я не мог понять, почему этот код не работает.
Рассмотрим следующий фрагмент, который работает как ожидалось:
const empty = [undefined, undefined];
const rand = empty.map(item => Math.random());
Output: [0.4774752874308936, 0.8482276976659398]
Я попытался упростить бит и сделать следующее
const rand = Array(2).map(item => Math.random())
Output: [undefined × 2]
Я не понимаю, почему это происходит. Очевидно, что оба массива, генерируемые Array (n) и [], являются типичными массивами и имеют все прототипы.
Array(2) instanceof Array
true
[undefined, undefined] instanceof Array
true
Array.isArray(Array(2))
true
Array.isArray([undefined, undefined])
true
Может кто-нибудь указать, где я здесь не так?
Ответы
Ответ 1
Array(2)
дает массив пустой с длиной 2
. Массивы JavaScript по своей сути разрежены (в них могут быть дыры, потому что они вообще не массивы), и что Array(2)
дает вам. Это выглядит так:
+−−−−−−−−−−−−−−+
| (array) |
+−−−−−−−−−−−−−−+
| length: 2 |
+−−−−−−−−−−−−−−+
тогда как ваш массив [undefined, undefined]
выглядит следующим образом:
+−−−−−−−−−−−−−−+
| (array) |
+−−−−−−−−−−−−−−+
| length: 2 |
| 0: undefined |
| 1: undefined |
+−−−−−−−−−−−−−−+
map
, forEach
, и большинство (но не всех) связанных методов на Array.prototype
только циклически просматривают фактические записи разреженного массива. Поскольку массив, возвращаемый Array(2)
, не имеет реальных записей, ваш обратный вызов никогда не вызывается.
ES2015 добавил Array#fill
(и его можно отрегулировать), который вы можете использовать для заполнения массива:
const rand = Array(2).fill().map(Math.random)
console.log(rand);
Ответ 2
Вы можете посмотреть спецификации Array#map
:
Он не вызывается для отсутствующих элементов массива (то есть индексов, которые никогда не были установлены, которые были удалены или которым никогда не назначено значение).
Вы можете использовать Array.apply для получения массива iterabel с картой.
console.log(Array.apply(null, { length: 2 }).map(Math.random));
Ответ 3
Это потому, что вы считаете, что Array(2)
интерпретируется движком JavaScript примерно так: "Создайте объект массива с двумя записями, инициализированными значением по умолчанию, например 0 или undefined
".
На самом деле, движок JavaScript создает новый объект и устанавливает его свойство length
равным 2. Он не имеет никакого реального контента.
Проверьте этот простой пример:
var arr = new Array(2);
console.log(arr);
Ответ 4
Вы создаете массив, инициализированный с размером 2. Но в этих позициях нет никакого элемента. то вы делаете
[undefined, undefined].map(item => Math.random())
У вас есть массив с двумя undefined элементами в нем.