Разница между массивом.применить (null, Array (x)) и Array (x)
в чем именно разница между:
Array(3)
// and
Array.apply(null, Array(3) )
первый возвращает [undefined x 3]
в то время как второй возвращает [undefined, undefined, undefined]
. Второй-цепной через Array.prototype.functions
например .map
, но первый-нет. Почему?
4 ответов
есть разница, довольно существенная.
на Array
конструктор или принимает одно единственное число, давая длину массива, и создается массив с "пустыми" индексами, или, правильнее, длина устанавливается, но массив на самом деле ничего не содержит
Array(3); // creates [], with a length of 3
при вызове конструктора массива с номером в качестве единственного аргумента вы создаете массив, который пуст, и который не может быть повторен с обычными методами массива.
или... конструктор массива принимает несколько аргументов, в то время как массив создается, где каждый аргумент является значением в массиве
Array(1,2,3); // creates an array [1,2,3] etc.
когда вы называете это
Array.apply(null, Array(3) )
это становится немного интереснее.
apply
принимает this
значение в качестве первого аргумента, и как это не полезно, это null
интересная часть второй аргумент, в котором передается пустой массив.
As apply
принимает массив, это было бы похоже на вызов
Array(undefined, undefined, undefined);
и это создает массив с тремя индексами, который не пуст, но имеет значение, фактически установленное в undefined
, поэтому его можно повторить.
TL; DR
Главное отличие в том, что Array(3)
создает массив с тремя пустыми индексами. На самом деле, они на самом деле не существуют, массив просто имеет длина 3
.
передача такого массива с пустыми индексами конструктору массива с помощью apply
это то же самое, что делать Array(undefined, undefined, undefined);
, который создает массив с тремя undefined
индексы, и undefined
фактически является значением, поэтому он не пуст, как в первом примере.
методы, такие как map()
можно только перебирать фактические значения, а не пустые индексы.
на .map()
API не выполняет итерацию по полностью неинициализированным элементам массива. Когда вы создаете новый массив с помощью new Array(n)
конструктор, вы получаете массив с .length
вы просили, но с несуществующими элементами, которые будут пропущены методы, такие как .map()
.
выражение Array.apply(null, Array(9))
явно заполняет вновь созданный экземпляр массива undefined
, но этого достаточно. Фокус в том, является ли in
оператор сообщит, что массив содержит элемент по заданному индексу. То есть:
var a = new Array(9);
alert(2 in a); // alerts "false"
это потому, что на самом деле нет элемента в позиции 2
в массиве. Но:
var a = Array.apply(null, Array(9));
alert(2 in a); // alerts "true"
внешний вызов конструктора массива будет явно заполнен элементами.
это артефакт того, как применить строительство. Когда вы делаете:
new Array(9)
создается пустой массив длиной 9. карта не посещает несуществующих членов, поэтому ничего не делает. Однако,применить превращает массив в список с помощью CreateListFromArrayLike таким образом, он превращает ранее пустой массив в список параметров, например:
[undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined];
это передается массив чтобы создать массив с 9 членами, все со значением неопределено. Так что теперь карта посетит их всех.
кстати, ECMAScript 2015 имеет массив.прототип.заполнить для этого (см. Также MDN) так что вы можете сделать:
Array(9).fill(0);
потому что первый массив не будет иметь упорядоченных свойств arr[0] === undefined
и второй делает. Функции массива, такие как forEach и map, будут повторяться от 0 до длины массива - 1, и отсутствие порядка для свойств первого является проблемой. Вторая версия создает массив с правильным порядком, т. е.
arr = Array.apply(null, Array(3));
arr[0] === undefined //true
arr[1] === undefined //true
//etc.
первая версия, как вы заметили, не. Кроме того, добавление new
для первой версии это не сработает.