在Javascript中的delete运算符

10 浏览
0 Comments

在Javascript中的delete运算符

这个问题已经有了答案:

JavaScript中删除数组元素-使用delete和splice

在书籍《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应该删除该元素,而浏览器决定不按照该规则实现?或者是书中错误了..?

admin 更改状态以发布 2023年5月23日
0
0 Comments

根据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不会受到影响。

0