2015-11-24 2 views
3

Я знаю, что универсальный способ изменения размера массива - использовать .push().Изменить размер массива, просто добавив элемент и не нажимать javascript

Однако, сегодня я видел кусок кода в angularJS, что делает что-то вроде этого:

var service = { 
    pages: [], 
    doSmth: doSmth 
}; 

doSmth(); 

function doSmth() { 
    service.pages[1] = "abc"; 
    service.pages[5] = "def"; 
} 

Я побежал отладчик браузера и обнаружил, что перед doSmth() называется, pages[1] не определен, но после того, , pages[1] присваивается значение без каких-либо ошибок.

Как это возможно?

+2

Поскольку страницы уже были инициализированы на страницах: []. Без страниц: [] вы увидите неопределенную ошибку. – tanjir

+3

Присвоение значений индексам на или после длины массива позволит изменить его размер. – Ryan

+0

Какое поведение вы ожидали? помните, что функция 'function doSmth' поднята – NicolasMoise

ответ

8

Это просто волшебство, которое позволяет JavaScript. Если вы исходите из такого языка, как Java или C, это может показаться странной идеей, но вы можете установить значение любого индекса в массиве в любой момент, и массив будет расширяться до такого размера!

Рассмотрим:

var t = []; 
t.length === 0; 
t[10000] = 'value'; 
t.length === 10001; 

JavaScript просто обрабатывает это за кулисами. Стоит отметить, что это поведение не характерно для JavaScript. Это видно и на других интерпретируемых языках. Ruby, например, позволяет вам делать то же самое.

Кроме того, в JavaScript, length является записываемым атрибутом массивов, так что вы можете легко обрезать или очистить весь массив:

var t = [1]; 
t[4] = 0; 
t === [1, undefined, undefined, undefined, 0]; 
t.length = 2; 
t === [1, undefined]; 
t.length = 0; 
t === []; 

Установку длиной 0, является одним из самых быстрых и простых способов очистить массив. Это может быть не самое интуитивное решение, но это мой подход.

+2

Примечание: массив не может * на самом деле * расширяться. Он будет вести себя так, как если бы это произошло, но внутренне, в зависимости от реализации, он, возможно, не наложил лишнего места. –

+1

И все это официально описано в спецификации http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.5.1 –

3

Массив в JavaScript - это просто объект с некоторыми специальными свойствами. По сути, это просто объекты с положительными целыми именами свойств. Есть некоторые другие ключевые различия, но идея состоит в том, что вы могли бы сделать это:

var obj = { }; 
obj['1'] = 'abc'; 

Таким образом, вы можете сделать то же самое с массивом.

Однако! Вы не должны. Современные JavaScript-движки обычно оптимизируют массивы, поддерживая их быстрыми встроенными реализациями. Установив индексы, которые в настоящее время не распределены, будет де-оптимизировать ваш код в нечто более похожее на объект, который намного медленнее.

+0

, но это не то, что происходит – CoderPi

+0

var obj = {}; <- вы инициализируете объект, а не массив. obj = [] - массив. – tanjir

+0

@CodeiSir: Каким образом? – Ryan

0

Страницы в function doSmth() не находится в том же пространстве имен, что и страницы в service, в которых service.pages.

Ваш pages[1] Мусульманин будет глобально объявлен где-то в другом месте.

Однако вы инициализации pages как пустой (но существующий) массив: pages: [],

var service = { 
    pages: [], 
    doSmth: doSmth 
}; 

doSmth(); 

function doSmth() { 
    pages[1] = "abc"; 
    pages[5] = "def"; 
} 
Смежные вопросы