Ответ 1
Итак, из того, что я мог сказать, он вызывал Array(), как будто ему было передано 10 аргументов, но поскольку он не определяет ни одно из этих "целочисленных свойств", он как будто он был передан 10 undefined аргументов. Это правильно?
Да, точно. Он делает это:
var arr = Array(undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined);
var barr = new Array(10); console.log(barr);
...
console.log(arr.map(function(item) { return 'hi';})); console.log(barr.map(function(item) { return 'hi';}));
Я хотел знать, почему функция карты не работает для второго.
Потому что map
, forEach
и аналогичные только свойства посещения фактически существуют. Как вы сказали, между ними большая разница.
var arr = Array(undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined);
// Or `var arr = Array.apply(null, {length: 10});
и
var barr = new Array(10);
В первом примере arr
имеет 10 записей, каждое из которых имеет значение undefined
. Во втором примере barr
имеет без записей и length
10
. Таким образом, в первом, map
будет посещать свойства, потому что они существуют. Во втором, это не будет, потому что они этого не делают.
Напомним, что стандартные массивы в JavaScript на самом деле не являются массивами (раскрытие: это сообщение в моем блоге), они объекты с некоторым особым поведением. Таким образом, они по своей сути являются скудными:
var a = [];
a.length = 10000;
a
не имеет 10 000 записей. У него нет записей. Просто это свойство length
10000
.
Вы можете определить, существует ли свойство с помощью hasOwnProperty
или in
. Для сравнения:
var barr = new Array(10);
console.log(barr.hasOwnProperty(0)); // false
console.log(0 in barr); // false
в
var arr = Array.apply(null, {length: 10});
console.log(arr.hasOwnProperty(0)); // true
console.log(0 in arr); // true
И
Array.apply
работает, потому что запрашивает{length: 10}
то, что имеет его свойство0
, получаетundefined
и поэтому присваиваетundefined
свойству0
построенного массива и т.д. Правильны ли мои рассуждения?
Да, хотя должно быть ясно, что он apply
спрашивает, что такое свойство 0
, а затем он использует это как первый аргумент при вызове Array
. Он Array
, который затем принимает значение первого аргумента и присваивает его свойству 0
в массиве, который он создает.
И действительно ли не менее хакерский способ определить массив, содержащий undefined целочисленные свойства для каждого индекса в пределах его диапазона, вместо того, чтобы вообще не иметь целочисленных свойств?
Только незначительно: ES2015 добавляет Array.from
, который принимает объект, подобный массиву, и возвращает истинный массив (необязательно сопоставляя записи). Итак, это будет:
var arr = Array.from({length:10});
Редко нужно делать это, а не просто a = new Array(bigNumberHere);
или a = []; a.length = bigNumberHere
. Например, много раз вам все равно, существует ли свойство или существует со значением undefined
. Иногда вы это делаете, но, чтобы дать вам перспективу, я профессионально писал JavaScript в течение 20 лет, довольно интенсивно, последние 8, и мне, вероятно, было интересно, о, один или два раза, вершины.
Вы упомянули, что в конкретном случае, с которым вы имели дело, он был объединен с map
, поэтому Array.from
займет место обоих:
var arr = Array.from({length: 10}, function() { return "hi"; });
... дает
["hi", "hi", "hi", "hi", "hi", "hi", "hi", "hi", "hi", "hi"]
Хотя Array.from
является новым в ES2015, он может быть зачищен/полилизован на старых машинах JavaScript.