Подтвердить что ты не робот

Является ли новый массив JavaScript с длиной непригодным для использования?

В соответствии с документация MDN для new Array(length) Я могу инициализировать массив с заданной длиной как таковой:

var a = new Array(10);
a.length; // => 10
a; // => [undefined x 10]

Однако, по-видимому, я не могу использовать такие методы, как map(...) для нового массива, хотя массивы, построенные другими способами, работают нормально:

a.map(function() { return Math.random(); });
// => [undefined x 10] -- wtf?
[undefined, undefined].map(function() { return Math.random(); });
// => [0.07192076672799885, 0.8052175589837134]

Почему это так?

Я понимаю из этого опыта (и поиска в Интернете), что конструктор массива с длиной является черной дырой необъяснимого поведения, но спецификация ECMA 262 дает объяснение?

4b9b3361

Ответ 1

new Array(10) не возвращает массив, заполненный 10 undefined s. Вместо этого он возвращает массив без элементов и с свойством length 10.

См. разницу:

var arr1 = new Array(1),
    arr2 = [undefined];
arr1.length === arr2.length; // Both are `1`
arr1[0] === arr2[1];         // Both are `undefined`
arr1.hasOwnProperty(0);      // false
arr2.hasOwnProperty(0);      // true

Поэтому методы массива ECMAScript 5 пропускают эти несуществующие свойства. В частности, когда они повторяются от 0 до length, они проверяют внутренний метод [[HasProperty]] массива.

Вы можете легко исправить это с помощью ECMAScript 6 Array.prototype.fill (который может быть polyfilled):

new Array(10).fill().map(Math.random);