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, если они недоступны.