删除操作符的行为似乎是very complicated and there are many misunderstandings about what it actually does。对我而言,似乎将某些内容重新分配给undefined
会更可靠地完成您期望的事情。
我从未在非示例代码中看到Javascript中实际使用的delete
关键字,我想知道它是否对任何内容特别有用。 delete
是否有任何通过重新分配到undefined
无法实现的目的?是否在任何着名的库(例如jQuery,dojo,backbone等)中都使用它? ?
答案 0 :(得分:66)
删除是否有任何通过重新分配到未定义而无法实现的目的?
是。如果您要从原型取消屏蔽属性或导致in
,hasOwnProperty
和for (...in...)
不将该属性记录为现有属性,则delete
是合适的。
var set = {};
set._x = true;
alert('_x' in set); // true
set._x = undefined;
alert('_x' in set); // true
delete set._x;
alert('_x' in set); // false
编辑:正如T.J.克劳德解释说:
delete
运算符的目的是从对象中完全删除属性,而将属性设置为undefined
只需将属性设置为undefined
。这本身就很重要,但是当你使用继承时它也很重要,因为如果O来源于P
var P = { prop: 42 };
var O = Object.create(P); // P is O's prototype.
当您检索
O.prop
时,如果O具有该名称的属性(即使其值未定义),则从O获取prop的值,但如果O根本没有该属性,则该值将从P.prop
中检索。
alert(O.prop); // "42" since O doesn't have its own prop, but P does.
O.prop = undefined;
alert(O.prop); // "undefined" since O has its own prop.
delete O.prop;
alert(O.prop); // "42" since the delete "unmasked" P.prop.
答案 1 :(得分:22)
正如Mike Samuel在他的回答中指出的那样,删除最常见的用法之一就是当你将一个对象视为一个将名称与值相关联的“属性包”时。 “此名称现在映射到某个虚假值”和“此名称根本没有映射”之间存在逻辑上的区别。 “删除”实现了后者。
这一切都得到了相当好的理解。我想我可能会添加一个关于JScript 1.0到5.0引擎的有趣历史记录。
在JScript的原始Microsoft实现中,我们使用OLE Automation样式的IDispatch对象来实现expando对象。 IDispatch当然通过将名称与“dispatch id”相关联来实现,“dispatch id”只是一个整数。要动态调用,首先要求dispatch对象为您提供与名称关联的调度ID,然后您说“现在调用与此ID关联的方法,给定这些参数”。
这一切都很好。但IDispatch合同的要求之一是从名称到调度ID的映射在对象的整个生命周期内是稳定的。因此,如果有人说“将属性Foo添加到此对象”,那么我们可能会确定属性Foo与该对象中的调度标识符0x1234相关联。从那一刻开始,每当对象被要求提供“Foo”的调度标识符时,它必须返回0x1234,,即使Foo被删除并随后再次添加。这允许调用者维护自己的名称/ dispid对的快速缓存,而不是总是在每次调用时都要询问对象。
实际结果是“删除”不会以任何方式减轻该实现中对象的内存负担!当您删除属性时(在原始实现中),我们必须在对象上添加一个位,标记将调度标识符删除,但是如果该名称返回,我们必须保留有关名称/ id配对的所有信息。向对象添加大量属性然后删除所有属性不会缩小内存中的对象。
JScript引擎当然已经完全重写了我的时间(除了,我相信,解析器和词法分析器)所以我不知道引擎是否还有这个不寻常的怪癖。找出来会很有趣。
答案 2 :(得分:10)
如果你这样做
delete Foo.Bar;
它完全从对象Foo中删除属性栏
Foo.Bar = undefined
仅将Bar属性设置为undefined,Foo.Bar
仍然存在
答案 3 :(得分:2)
其他答案正在解释delete
关键字背后的动机。我想补充一点,截至2017年,浏览器在删除属性和将属性设置为undefined时都会释放内存。
考虑这个例子(source of roughSizeOfObject()
):
> var obj = {a:42,b:"b"}; roughSizeOfObject(obj)
26
> obj.a = undefined; roughSizeOfObject(obj)
18
> delete obj.a; roughSizeOfObject(obj)
10
> obj.b = undefined; roughSizeOfObject(obj)
8
> delete obj.b; roughSizeOfObject(obj)
0
示例来自Chrome 61(64位)控制台(请注意String
中的所有字符都在内部编码为16位无符号整数。)
答案 4 :(得分:1)
您可以查看以下链接Can I set variables to undefined or pass undefined as an argument?的答案,以非常详细的方式解释差异。
要点:
您当然可以为其分配undefined,但不会删除 变量。只有删除object.property运算符才能真正删除 的东西。
delete实际上是指属性而不是变量。 浏览器会让你直接删除变量,但它是 不是一个好主意,也不适用于ECMAScript第五版的严格要求 模式。如果你想释放对某事物的引用,那就可以了 垃圾收集,更常见的是变量= null。
答案 5 :(得分:0)
好吧,你最终会在对象中包含一个包含值undefined
的元素。关键不会消失。