在Javascript中的delete运算符
在Javascript中的delete运算符
这个问题已经有了答案:
在书籍《Javascript: The definitive guide》的第六版中,第4.13.3章节中给出了以下内容:
delete操作符
var a = [1,2,3]; // Start with an array delete a[2]; // Delete the last element of the array a.length // => 2: array only has two elements now
但是,当我在Firefox和chrome中尝试上面的片段时,数组的长度仍然是3。
这是书籍中的错误信息,还是浏览器中javascript的实现与javascript规范不同?
注意:我尝试了splice
,它删除了元素。我的疑惑是,是否有ecmascript规范中规定,delete应该删除该元素,而浏览器决定不按照该规则实现?或者是书中错误了..?
根据MDN的说法:
删除数组元素时,数组长度不会受到影响。即使您删除数组的最后一个元素也是如此。
因此,您的最后一个假设(“数组现在只有两个元素”)是错误的。正如RobG在注释中指出的那样,这是错误的,原因有两点:
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
属性可以更改以截断数组,但是它不会影响删除(删除)数组项,因为它不会执行任何赋值操作(因此§15.4.5.1不适用)。您会得到undefined
,因为现在不存在这样的成员,并且根据§8.6.1的规定,结果是undefined
。
我认为(但这只是猜测),混淆出现在§15.4.5.2中,他们在其中说:
此Array对象的length属性是数据属性,其值始终比每个可删除属性的名称大,其名称是数组索引。
根据这个单句,从数组中删除最后一个元素也可能会减少其长度。这种行为不符合§15.4.5.1,标准只是指出length
大于……数组索引,而不是最高索引+1。
简而言之,delete
运算符仅删除成员,但length
不会受到影响。