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);

答案 0 :(得分:9)
引用ECMA脚本5规范Array Objects,
当且仅当
P
等于ToString(ToUint32(P))
并且P
不相等时,属性名称ToUint32(P)
(以String值的形式)是一个数组索引到2 32 -1。
由于Hello
无效,根据上面的定义,它不被视为数组索引,而是普通属性。
引用MDN' Relationship between length and numerical properties section,
当属性是有效数组索引时在JavaScript数组上设置属性并且该索引超出数组的当前边界时,引擎将更新数组的长度属性相应
因此,仅当属性是有效的数组索引时,才会调整length
属性。
在您的情况下,您刚刚在数组对象上创建了一个新属性Hello
。
注意:只有数字属性才会用于Array
的所有原型函数,例如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
将包含在键中,但特定于数组的函数将仅包含数字属性。
答案 1 :(得分:1)
这是因为length
仅在将新的数字属性添加到数组as required by the specification时更新:
此Array对象的length属性是一个data属性,其值始终在数值上大于名称为数组索引的每个deletable属性的名称。
数组索引is specified to be:
当且仅当ToString(ToUint32(P))等于P且ToUint32(P)不等于232-1时,属性名P(以String值的形式)是数组索引。
但是,数组也是对象 - 因此您可以向数组添加非数组索引属性,就像您可以向任何其他JavaScript对象添加属性一样(这就是为什么您的示例也不会抛出)。
答案 2 :(得分:0)
javascript长度计算为1+(最高数字索引元素)。因此,当您添加arr['Hello']
时,您只需添加一个字符串索引,在计算数组长度时不会将其考虑在内。
每个Array对象都有一个length属性,其值始终为a 非负整数小于2 32 。 length属性的值是 在数字上大于名称为a的每个属性的名称 数组索引;每当创建Array对象的属性时 更改后,其他属性会根据需要进行调整以维持此状态 不变的。具体来说,每当添加名称为的属性时 数组索引,如果需要,将更改长度属性为1 超过该数组索引的数值;无论什么时候 length属性已更改,每个属性的名称都是数组 其值不小于新长度的索引是自动的 删除。此约束仅适用于Array的自身属性 对象并且不受可能的长度或数组索引属性的影响 继承自原型。
答案 3 :(得分:0)
当你写:
ARR ["你好"] = ...
您正在创建与arr
数组对象关联的新对象,该对象不会影响arr
的长度。
您可以通过写作来实现相同的效果:
arr.Hello = ...