2015-02-09 2 views
9

Что именно разница между:Разница между Array.apply (нуль, Array (х)) и Array (х)

Array(3) 
// and 
Array.apply(null, Array(3)) 

Первые возвращает [undefined x 3] в то время как второй возвращает [undefined, undefined, undefined]. Второй - с цепью через Array.prototype.functions, такой как .map, но первый - нет. Зачем?

+0

'Array.apply (нуль, Array (9))' * не * 'новый Array (9) '. Он распределяет 'Array (9)' в 'Array()' как девять параметров. Даже если это работает, это в значительной степени неправильный путь. Например, вы можете 'new Array (1e7)', но не 'Array.apply (null, Array (1e7))'. – Sheepy

+1

Связанный: http://stackoverflow.com/questions/22949976/why-does-array-applynull-args-act-inconsistently-when-dealing-with-sparse-a – Sheepy

ответ

13

Есть разница, довольно значительная.

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

Интересная частью является вторым аргументом, где пустой массив передается в.
Как apply принимает массив, то он был бы как вызов

Array(undefined, undefined, undefined); 

и создает массив с тремя индексами, это не пустой, но иметь значение фактически установлен в undefined, поэтому она ча n повторяться.

TL; DR
Основное отличие заключается в том, что Array(3) создает массив с тремя индексами, которые пусты. На самом деле, они действительно не существуют, массив имеет длину 3.

Передача такого массива с пустыми индексами конструктору Array, используя apply так же, как делает Array(undefined, undefined, undefined);, который создает массив с тремя undefined индексами и undefined в действительности значение, так что это не пустая, как в первом пример.

Методы массива, такие как map(), могут выполнять итерацию только по фактическим значениям, а не по пустым индексам.

0

Поскольку первый массив не имел упорядоченных свойств arr[0] === undefined, а второй делает.Функции массива, такие как forEach и map, будут перебираться с 0 на длину массива - 1, а проблема отсутствия первого свойства - проблема. Вторая версия производит массив с правильным порядком, то есть

arr = Array.apply(null, Array(3)); 
arr[0] === undefined //true 
arr[1] === undefined //true 
//etc. 

Первая версия, как вы ее заметили, отсутствует. Кроме того, добавление new к первой версии не заставит его работать.

11

API .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" 

Внешний вызов конструктора массива будет явно заполнен элементами.

+0

Спасибо за ответ, я не был действительно уверен что то, что было в каждом слоте, не совпадает с неопределенным значением, поскольку индексирование в любую заданную позицию возвращает неопределенный. –

+1

@ mb_s88 считать '0 в массиве (9); // false' –

+0

@ mb_s88 answer extended little – Pointy

3

Это артефакт как применить работы. Когда вы делаете:

new Array(9) 

пустой массив создаются с длиной 9 карты не посетить несуществующие пользователь, поэтому не делает ничего. Тем не менее, apply превращает массив в список с помощью CreateListFromArrayLike поэтому превращает ранее пустой массив в список параметров, как:

[undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined]; 

, который передается массива создать массив с 9 членов, все со значением от undefined. Итак, теперь карта посетит их всех.

BTW, ECMAScript 2015 имеет Array.prototype.fill для этого (также см MDN), так что вы можете сделать:

Array(9).fill(0); 
Смежные вопросы