Array.map, похоже, не работает на неинициализированных массивах
Я пытаюсь установить значения по умолчанию в неинициализированном массиве, используя функцию map, но, похоже, не работает, какие-либо идеи о том, как устанавливать значения по умолчанию?
Рассмотрим этот фрагмент кода, который я пробовал в консоли Chrome.
> var N = 10;
> var x = new Array(N);
> x
[undefined x 10]
> x.map(function(i) { return 0;});
[undefined x 10]
Я ожидал, что массив будет инициализирован 0.
Ответы
Ответ 1
Если вы хотите заполнить массив, вы можете сделать это
Array.apply(null, new Array(5)).map(function() { return 0; });
// [ 0, 0, 0, 0, 0 ]
После некоторого чтения одной из сообщений, связанных в комментариях, я обнаружил, что это также можно записать как
Array.apply(null, {length: 5}).map(function() { return 0; });
Однако попытка использования значений .map
on undefined не будет работать.
x = new Array(10);
x.map(function() { console.log("hello"); });
// so sad, no "hello"
// [ , , , , , , , , , ]
.map
будет пропускать значения undefined: (
Ответ 2
Я хотел бы отметить, что теперь вы можете:
Array(2).fill().map(_ => 4);
Это вернет [4, 4]
.
Ответ 3
То, как описано в спецификации языка ECMAScript
Здесь соответствующая часть Array.prototype.map
, как описано (§15.4.4.19)
- ...
- 8. Повторите, а
k < len
- a) Пусть
Pk
be ToString(k)
.
- b) Пусть
kPresent
является результатом вызова внутреннего метода [[HasProperty]] O
с аргументом Pk
.
- c) Если
kPresent
true
, то
- ...
Поскольку в вашем массиве нет инициализированного члена, вызов e.g new Array (1337).hasOwnProperty (42)
оценивается как false
, поэтому условие на шаге 8.c не выполняется.
Однако вы можете использовать небольшой "взлом", чтобы делать то, что хотите.
Array.apply(null, { length: 5 }).map(Number.call, Number) //[0, 1, 2, 3, 4]
Как это работает, было объяснено @Zirak
Ответ 4
Функция .map()
пропускает записи, никогда не назначаемые значения. Таким образом, на вновь построенном массиве, подобном вашему, он практически ничего не делает.
Ниже приведено описание MDN.
Ответ 5
С .map()
элементы undefined пропускаются и не передаются обратному вызову, поэтому, если у вас есть массив без элементов, которые фактически содержат что-либо, тогда обратный вызов никогда не вызывается.
Из ECMA script 262, спецификация 5.1, раздел 15.4.4.19:
callbackfn вызывается только для элементов массива, которые фактически существовать; он не вызывается для отсутствующих элементов массива.
Ответ 6
Вы можете заполнить массив нулями с помощью этой функции:
function fillArrayWithNumber(n) {
var arr = Array.apply(null, Array(n));
return arr.map(function (x, i) { return 0; });
}
fillArrayWithNumber(5); // [0,0,0,0,0]
Или с небольшим изменением вы можете использовать индексы вместо:
function fillArrayWithIndex(n) {
var arr = Array.apply(null, Array(n));
return arr.map(function (x, i) { return i; });
}
fillArrayWithIndex(5); // [0,1,2,3,4]
Fiddle
Ответ 7
Основываясь на предыдущем ответе, появляется новый более короткий синтаксис. OP хотел создать массив из N элементов, инициализированных с помощью 0.
var N = 10;
var x = new Array(N).fill(0);
// x is now: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
Вам также не нужен new
- он необязательный в этом контексте.
Проверьте совместимость вашей целевой платформы и/или используйте pollyfill, если они недоступны.