2015-04-29 2 views
6

Почему не изменяется длина массива при добавлении нового свойства?

var arr = ["Hello", "There", 123, 456, { 
 
    show: function (value) { 
 
     alert(value); 
 
    } 
 
}]; 
 
arr[4].show(arr[0]); 
 
arr["Hello"] = { 
 
    damn: function() { 
 
     alert("What's happening yo !"); 
 
    } 
 
} 
 
arr.Hello.damn(); 
 
alert("Arr length is: " + arr.length);

+4

Массив должен иметь только цифровые клавиши. Любые нечисловые ключи не будут учитываться для длины. – elclanrs

ответ

9

Цитирование ECMA Сценарий 5 Спецификация ,

Имя свойства P (в виде значения String) является индексом массива тогда и только тогда, когда ToString(ToUint32(P)) равно P и ToUint32(P) не равна 2 -1.

Поскольку Hello недействителен, в соответствии с вышеприведенным определением он не рассматривается как индекс массива, а как обычное свойство.

Цитирование MDN-х Relationship between length and numerical properties section,

При установке свойства в массиве JavaScript, когда свойство является допустимым индексом массива и что индекс находится вне текущих границ массива, двигатель обновит массив соответственно

Таким образом, только если свойство является допустимым индексом массива, свойство length будет скорректировано.

В вашем случае вы только что создали новое свойство Hello объекта массива.


Примечание: только числовые свойства будут использоваться во всех функций прототипа Array «s, как forEach, map и т.д.

Например, массив показан на вопрос, когда используется с forEach,

arr.forEach(function(currentItem, index) { 
    console.log(currentItem, index); 
}) 

напечатает

Hello 0 
There 1 
123 2 
456 3 
{ show: [Function] } 4 

даже если список ключей показывает Hello.

console.log(Object.keys(arr)); 
// [ '0', '1', '2', '3', '4', 'Hello' ] 

Это происходит потому, что Array происходит от Object,

console.log(arr instanceof Object); 
// true 

и Hello является допустимым ключом объекта массива, но только не является допустимым индексом массива. Таким образом, когда вы обрабатываете массив как объект, в ключи будут включены Hello, но конкретные функции массива будут включать только числовые свойства.

+0

да!длина не увеличивается, если значение сохраняется как стиль «ассоциативного массива». – Sandeep

1

Это происходит потому, что length обновляется только когда новый числовой свойство добавляется в массив as required by the specification:

Длина свойство этого массива объекта является свойством данных которого значение всегда численно больше, чем имя каждого удаляемого свойства, имя которого является индексом массива.

и индекс массива is specified to be:

Имя свойства Р (в виде значения String) является индексом массива тогда и только тогда, когда ToString (ToUint32 (Р)) равна Р и ToUint32 (P) не равно 232-1.

Однако массивы также являются объектами - поэтому вы можете добавлять свойства массива без массива в массив, так же как вы можете добавлять свойства к любому другому объекту JavaScript (поэтому ваш пример не бросает) ,

0

Длина javascript рассчитывается как 1+ (самый высокий элемент числового индекса). поэтому, когда вы добавляете arr['Hello'], вы добавляете только строковый индекс, который не учитывается при вычислении длины массива.

Это фактическое определение свойства длины массива, как описано в ECMAScript 5.1:

Каждый объект Массив имеет свойство длины, значение которого всегда неотрицательное целое число меньше, чем 2 . Значение свойства length равно , численно больше имени каждого свойства, имя которого является индексом массива ; всякий раз, когда создается свойство объекта Array или изменяется , другие свойства корректируются по мере необходимости для поддержания этого инварианта . В частности, всякий раз, когда добавляется свойство, чье имя является индексом массива , свойство длины изменяется, если необходимо, на одно больше, чем числовое значение этого индекса массива; и всякий раз, когда изменяется свойство длины , каждое свойство, имя которого представляет собой массив индекс, значение которого не меньше, чем новая длина, автоматически удалено. Это ограничение применимо только к собственным свойствам объекта Array и не зависит от свойств индекса длины или массива, которые могут быть унаследованы от его прототипов .

+0

Также добавить: http://es5.github.io/#x15.4.5.2 –

0

Когда вы пишете:

обр [ "Hello"] = ...

вы создаете новый объект, связанный с объектом arr массива, который не влияет на длина arr.

Вы можете достичь того же эффекта, написав:

arr.Hello = ...

Смежные вопросы