这是因为
delete
运算符删除属性,被删除的属性的值为
undefined
。要从数组中删除元素,可以使用数组的
splice
方法。
所有这些都是因为 JavaScript 中 delete 运算符的工作方式。
当您没有设置对象的属性并尝试检查其值时,它将为 undefined:
var obj = {};
alert(obj.foo); // undefined
这与以下内容相同:
alert(obj['foo']); // undefined
再看这个:
// create empty object
var obj = {};
// check its property named 1
alert(obj[1]); // undefined
// set property named 1 to value 'fooo'
obj[1] = 'fooo';
// and check it
alert(obj[1]); // 'fooo'
// now delete it
delete obj[1];
// and check again
alert(obj[1]); // undefined
delete
已经删除了属性,其值为undefined
- 而且以上所有代码都是关于对象的。
现在看看数组:
var arr = [];
alert(arr[1]);
arr[1] = 'fooo'
alert(arr[1]);
delete arr[0];
alert(arr[1]);
行为是相同的,但数组的length
属性呢?规范http://es5.github.com/#x15.4.5.2说:
“该Array对象的length属性是一个数据属性,其值始终数值上大于每个可删除属性的名称是数组索引的名称。”
所以当你看到这个:
var arr = ['foo', 'bar', 'foobar'];
alert(arr.length);
delete arr[1];
alert(arr.length);
上一次检查返回 3,因为此数组中最后一个可删除属性具有索引 2 - 第一个属性(索引 0)具有值 undefined(删除运算符设置了这个值),第二个项(索引 1)具有值 'bar',第三个(索引 2)具有值 'foobar'。因此,根据规范长度 = 2 + 1('始终数值大于最后可删除项');
这也可以在以下代码中看到:
var arr = [];
arr[10] = 'foo';
// element with index 10 is set to 'foo' but elements from 0 to 9 don't have value - they are undefined
// now check length
alert(arr.lenght); // 11
最后可删除的属性索引是10,因此10 + 1等于11,尽管之前的元素未定义。
因此,删除运算符可以完成其工作,但它并不是设计用于从数组中删除项目的。
Array
。(但如果它使用了,答案仍然是正确的;JavaScript数组实际上并不是真正的数组,请参阅我的答案以获取详细信息。) - T.J. Crowderdelete
不按你的预期工作是完全有道理的。delete
在更低层次上直接作用于对象属性。它不“知道”你正在修改的对象是一个数组。如果.length
的值是在访问时确定的,情况就不同了,但它并不是这样。 - Felix Kling+
运算符为例。它在不同的构造函数(Number vs Array)中变异行为毫不犹豫。相比之下,delete
则要简单得多。如果你问我,与根据操作数产生不同返回类型的+
相比,更新数组的length
的delete
操作听起来相当合理。 - Saulnew Number() + new Number()
和new Array() + new Array()
。 这两个操作都涉及到魔法,但归根结底,+
对于不同的构造函数提供了不同的行为。这就是我想知道delete
为什么会是现在这样的特殊原因。 - Saul