根据MDN:
删除数组元素时,数组长度不受影响。即使您删除了数组的最后一个元素,这仍然成立。
那么你的最后一个假设是错误的(“数组现在只有两个元素”)。正如 RobG 在 cmets 中指出的那样,这是错误的,原因有两个:
-
Array.length 是数组的长度(参见后面引用的最后一个 §15.4.5.2),而不是它包含的元素数。
- 在您的情况下,
a.length 不是两个而是三个,因为delete 不会修剪数组。
这是什么意思?那条评论是对的(a 有两个元素)但代码是错误的(数组长度仍然是三个)。
当你从数组中删除一个元素时,你得到的是undefined 而不是那个元素(当你尝试访问那个索引时):
var a = [1,2,3]; // a == [1, 2, 3]
delete a[2]; // a == [1, 2, undefined]
来自ECMAScript Language Specification。
delete 运算符在 §11.4.1 中进行了描述。它说[[Delete]] 数组内部方法将被调用。现在我们知道(来自§8.6.2)我们应该检查[[DefineOwnProperty]] 数组内部方法,因为仅仅删除索引属性是不够的。从 §15.4.5.1 我们可以看到 length 属性可以更改为 truncate array 但它不会影响删除(删除)一个数组项,因为它不会做任何赋值(然后§15.4.5.1 将不适用)。你会得到undefined,因为现在没有这样的成员,根据§8.6.1结果是undefined。
在我看来(但这只是推测)混淆源于 §15.4.5.2 他们说:
此 Array 对象的长度属性是一个数据属性,其值在数值上始终大于名称为数组索引的每个可删除属性的名称。
根据这句话,删除数组的最后一个元素可能也会减少它的长度。这种行为不符合 §15.4.5.1 并且标准只是声明length 大于...数组索引,而不是最高索引 + 1。
简而言之:delete 运算符只是删除一个成员,但length 不受影响。