添加新属性时,为什么数组的长度没有变化?

Sto*_*orm 7 javascript arrays

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);
Run Code Online (Sandbox Code Playgroud)

the*_*eye 9

引用ECMA脚本5 数组对象的规范,

属性名称P(在一个字符串值的形式)是一个数组索引当且仅当ToString(ToUint32(P))是等于PToUint32(P)不等于2 32 -1.

由于Hello无效,根据上面的定义,它不被视为数组索引而是普通属性.

引用MDN的长度和数值属性部分之间关系,

当属性是有效的数组索引并且该索引超出数组的当前边界时,在JavaScript数组上设置属性时,引擎将相应地更新数组的长度属性

因此,仅当属性是有效的数组索引时,length才会调整属性.

在您的情况下,您刚刚在Hello数组对象上创建了一个新属性.


注意:只有数值的属性将在所有的被使用Array的原型功能,如forEach,map等.

例如,显示的数组与使用时一样forEach,

arr.forEach(function(currentItem, index) {
    console.log(currentItem, index);
})
Run Code Online (Sandbox Code Playgroud)

会打印

Hello 0
There 1
123 2
456 3
{ show: [Function] } 4
Run Code Online (Sandbox Code Playgroud)

即使按键列表显示Hello.

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

这是因为,Array源于Object,

console.log(arr instanceof Object);
// true
Run Code Online (Sandbox Code Playgroud)

并且Hello是数组对象的有效键,但不是有效的数组索引.因此,当您将数组视为Object时,Hello将包含在键中,但特定于数组的函数将仅包含数字属性.