为什么delete会保留Array元素?

Sau*_*aul 11 javascript operators

今天我偶然发现了一个关于Stack Overflow的问题 - 如何从javascript关联数组中删除对象?.让我感到震惊的是,接受的答案既误导又反对,所以我强调了可能的陷阱.

然而,在纠正错误答案的同时,我意识到我不知道为什么delete保持元素分配 undefined而不是删除是有意义的.

var elements = new Array()
elements.push(NaN)
elements.push(NaN)
elements.push(NaN)
delete elements[1]
console.log("number of elements: ", elements.length)   // returns 3
Run Code Online (Sandbox Code Playgroud)

它背后有理由吗?

T.J*_*der 11

我意识到我不知道为什么delete分配undefined而不是删除是有意义的.

它没有.delete从对象中删除属性,它并没有将它们设置为undefined.这是一个简单的方法:

var a = ['a', 'b', 'c'];
console.log(1 in a); // logs "true"
delete a[1];
console.log(1 in a); // logs "false"
Run Code Online (Sandbox Code Playgroud)

注意,之后delete,a没有一个叫做的属性1了.完全没有.

对比:

var a = ['a', 'b', 'c'];
console.log(1 in a); // logs "true"
a[1] = undefined;
console.log(1 in a); // logs "true"
Run Code Online (Sandbox Code Playgroud)

在那里,a仍然有一个叫做的属性1,它只是属性的值undefined.

理解在JavaScript中,数组根本不是真正的数组,这很有用.它们只是对象,数组"索引"只是属性名称(它们是字符串 - 是的,实际上,我们只是将它们写成数字),数组具有特殊的属性名称处理,这些属性都是数字(索引),特殊的length财产,以及他们从中获得的一些功能Array.prototype.这在规范的第15.4节中非常清楚地阐述.一旦你坚定地认为JavaScript数组不是真正的数组,它们就更有意义了.:-)

从数组中删除数组"index"属性不会更改它length(即使删除编号最大的数组也不会); 它只是在数组中创建一个洞(JavaScript"数组"本质上是稀疏数组;例如,它们可能有间隙).所以在我上面的第一个例子中,如果我这样做的话,我会得到完全相同的数组:

var a = [];
a[0] = 'a';
a[2] = 'c';
Run Code Online (Sandbox Code Playgroud)

注意间隙,数组没有1元素/属性.

如果你说:

var foo = a[3];
Run Code Online (Sandbox Code Playgroud)

... foo可以获得undefined两个完全不同的原因:

  1. a有一个名为3具有值的属性undefined,或:
  2. a根本没有任何财产3; 对于没有该名称属性的对象的属性访问器操作的结果是undefined.这个if-no-property- return-undefined以相当复杂的方式涵盖了规范,但主要在8.12.3节中.

这是非常不同的事情.

  • @Saul:`length`属性只是数组中编号最大的属性加一.试试`var a = new Array(); a [100] = 1; 警报(则为a.length);` (2认同)

Que*_*tin 6

它不分配undefined.它删除了该属性.(如果您尝试访问不存在的属性,您将获得undefined,并且length基于数组中编号最大的项).

这是有道理的,因为它可以在任何类型的对象上运行.对于它的行为,如果它们是一个特殊的案例对象,它只需要具有instanceof Array数字名称的属性.

使用splice,如果你想从一个数组中删除的项目.

> var elements = [NaN, NaN, NaN];
> elements.splice(1,1);
> console.log(elements);
[ NaN, NaN ]
Run Code Online (Sandbox Code Playgroud)