Является ли новый массив 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 дает объяснение?
Ответы
Ответ 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);