Javascript 中删除运算符的目的是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8945276/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 05:06:20  来源:igfitidea点击:

What is the purpose of the delete operator in Javascript?

javascript

提问by Peter Olson

The behaviour of the delete operator seems very complicated and there are many misunderstandings about what it actually does. To me, it seems that reassigning something to undefinedwill more reliably do what you would expect.

delete 操作符的行为看起来非常复杂,而且对于它的实际作用存在很多误解。对我来说,似乎重新分配某些东西undefined会更可靠地完成您的期望。

I've never seen the deletekeyword in Javascript actually used in non-example code and I am wondering if it is particularly useful for anything. Does deletehave any purpose that cannot be acheived by reassignment to undefined?Is it used at all in any of the famous libraries (e.g. jQuery, dojo, backbone, etc)?

我从未delete在非示例代码中实际使用过 Javascript 中的关键字,我想知道它是否对任何东西都特别有用。是否delete有任何不能通过重新分配到 来实现的目的undefined它是否在任何著名的库(例如 jQuery、dojo、backbone 等)中使用过?

回答by Mike Samuel

Does delete have any purpose that cannot be acheived by reassignment to undefined?

删除是否有任何不能通过重新分配给 undefined 来实现的目的?

Yes. If you want to unmask a property from a prototype or cause in, hasOwnProperty, and for (...in...)to not record the property as existing then deleteis appropriate.

是的。如果你想从一个原型或造成财产揭露inhasOwnProperty以及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

EDIT: As T.J. Crowder explains:

编辑:正如 TJ Crowder 解释的那样:

The purpose of the deleteoperator is to completely remove a property from an object, whereas setting a property to undefinedjust sets the property to undefined.

This matters in its own right, but it also matters when you're using inheritance, because if O derives from P

delete运算符的目的是从对象中完全删除属性,而将属性设置为undefined仅将属性设置为undefined

这本身很重要,但在使用继承时也很重要,因为如果 O 派生自 P

var P = { prop: 42 };
var O = Object.create(P);  // P is O's prototype.

when you retrieve O.prop, you get the value of prop from O if O has a property with that name (even if its value is undefined), but if O doesn't have the property at all, then the value will be retrieved from P.propinstead.

当您检索 时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.

回答by Eric Lippert

As Mike Samuel points out in his answer, one of the most common usages of delete is when you are treating an object as a "property bag" that associates names with values. There is logically a difference between "this name is now mapped to some bogus value" and "this name is not mapped at all". "delete" achieves the latter.

正如 Mike Samuel 在他的回答中指出的那样,delete 最常见的用法之一是当您将对象视为将名称与值相关联的“属性包”时。“这个名字现在被映射到某个虚假值”和“这个名字根本没有被映射”在逻辑上是有区别的。“删除”实现了后者。

That's all reasonably well understood. I thought I might add an interesting historical note regarding the JScript 1.0 through 5.0 engines.

这一切都很好理解。我想我可以添加一个关于 JScript 1.0 到 5.0 引擎的有趣历史注释。

In those original Microsoft implementations of JScript we used OLE Automation-style IDispatch objects to implement expando objects. IDispatch of course works by associating a name with a "dispatch id", which is simply an integer. To invoke dynamically, first you ask the dispatch object to give you the dispatch ID associated with a name, and then you say "now invoke the method associated with this ID, given these arguments".

在 JScript 的那些原始 Microsoft 实现中,我们使用 OLE 自动化样式的 IDispatch 对象来实现 expando 对象。IDispatch 当然是通过将名称与“调度 ID”相关联来工作的,“调度 ID”只是一个整数。要动态调用,首先您要求调度对象为您提供与名称关联的调度 ID,然后您说“现在调用与此 ID 关联的方法,给定这些参数”。

That's all well and good. But one of the requirements of the IDispatch contract is that the mapping from name to dispatch ID be stable over the entire lifetime of the object. So if someone says "add property Foo to this object", then we might decide that property Foo is associated with dispatch identifier 0x1234 in that object. From that moment on, every timethe object is asked for the dispatch identifier of "Foo", it must give back 0x1234, even if Foo is deleted and subsequently added again.This permits a caller to maintain their own fast cache of name/dispid pairs rather than always having to ask the object on every invocation.

这一切都很好。但是 IDispatch 契约的要求之一是从名称到调度 ID 的映射在对象的整个生命周期内保持稳定。因此,如果有人说“将属性 Foo 添加到此对象”,那么我们可能会决定属性 Foo 与该对象中的调度标识符 0x1234 相关联。从那一刻起,每次向对象询问“Foo”的调度标识符时,它必须返回 0x1234,即使 Foo 被删除并随后再次添加。这允许调用者维护他们自己的名称/dispid 对的快速缓存,而不是每次调用时都必须询问对象。

The practical upshot of that is that "delete" does not in any way lessen the memory burden on the object in that implementation! When you delete a property (in the original implementation) we must add a bit to the object marking that dispatch identifier as deleted, but we must retain all the information about the name/id pairing in case that name ever comes back. Adding a huge number of properties to an object and then deleting all of them does not shrink the object in memory.

其实际结果是“删除”不会以任何方式减轻该实现中对象的内存负担!当您删除一个属性(在原始实现中)时,我们必须向对象中添加一点,将调度标识符标记为已删除,但我们必须保留有关名称/ID 配对的所有信息,以防该名称再次出现。向对象添加大量属性然后删除所有属性不会缩小内存中的对象。

The JScript engine has of course been completely rewritten since my time (except for, I believe, the parser and lexer) so I have no idea if the engine still has this unusual quirk. It would be interesting to find out.

JScript 引擎当然从我那个时代开始就被完全重写了(我相信,除了解析器和词法分析器),所以我不知道引擎是否仍然有这个不寻常的怪癖。找出答案会很有趣。

回答by parapura rajkumar

If you do

如果你这样做

 delete Foo.Bar;

it deletes the property Bar from object Foo entirely

它从对象 Foo 中完全删除了属性 Bar

 Foo.Bar = undefined

merely sets Bar property to undefined and Foo.Barstill exists

只是将 Bar 属性设置为 undefined 并且Foo.Bar仍然存在

回答by syntagma

The other answers are explaining the motivation behind the deletekeyword. I would like to add that as of 2017, browser do deallocate memoryboth when deleting a property and when setting the property to undefined.

其他答案正在解释delete关键字背后的动机。我想补充一点,截至 2017 年,浏览器在删除属性和将属性设置为未定义时都会释放内存

Consider this example (source of roughSizeOfObject()):

考虑这个例子(来源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

The example comes from Chrome 61 (64-bit) console (note that all characters in Stringare internally encoded as 16-bit unsigned integer).

该示例来自 Chrome 61(64 位)控制台(请注意,其中的所有字符都在String内部编码为 16 位无符号整数)。

回答by Adel Boutros

You can check the answer of the following link Can I set variables to undefined or pass undefined as an argument?which explains the difference in a very detailed way.

您可以查看以下链接的答案Can I set variables to undefined or pass undefined as an argument? 这以非常详细的方式解释了差异。

Summary:

概括:

You can certainly assign undefined to it, but that won't delete the variable. Only the delete object.property operator really removes things.

delete is really meant for properties rather than variables as such. Browsers will let you get away with straight delete variable, but it's not a good idea and won't work in ECMAScript Fifth Edition's strict mode. If you want to free up a reference to something so it can be garbage-collected, it would be more usual to say variable= null.

您当然可以将 undefined 分配给它,但这不会删除变量。只有 delete object.property 操作符才能真正删除东西。

delete 实际上是用于属性而不是变量本身。浏览器可以让你直接删除变量,但这不是一个好主意,并且在 ECMAScript Fifth Edition 的严格模式下不起作用。如果你想释放对某物的引用以便它可以被垃圾收集,通常说 variable=null 会更常见。

回答by James McLaughlin

Well, you'd end up with an element in your object that contains the value undefined. The key wouldn't be gone.

好吧,您最终会在对象中得到一个包含 value 的元素undefined。钥匙不会消失。