ChatGPT解决这个技术问题 Extra ChatGPT

我对 JavaScript 的 delete 运算符有点困惑。采取以下代码:

var obj = {
    helloText: "Hello World!"
};

var foo = obj;

delete obj;

这段代码执行后,objnull,但 foo 仍然指代与 obj 完全相同的对象。我猜这个对象与 foo 指向的对象相同。

这让我感到困惑,因为我预计写入 delete obj 会删除 obj 在内存中指向的对象,而不仅仅是变量 obj

这是因为 JavaScript 的垃圾收集器在保留/释放的基础上工作,所以如果我没有任何其他变量指向该对象,它将从内存中删除?

(顺便说一下,我的测试是在 Safari 4 中完成的。)

有关删除关键字 webcache.googleusercontent.com/… 的完整文章
上面的链接应该是:perfectionkills.com/understanding-delete
@Steve Harrison delete 不是用于删除 javascript 中的对象 delete 用于在您的情况下删除对象键 var obj = { helloText: "Hello World!" }; var foo = obj; delete obj; 对象未删除检查 obj 删除用法:delete obj.helloText 然后检查 foo now foo is an empty object
@UmairAhmed,免费翻译:""" delete 不用于删除 javascript 中的对象。delete 用于删除对象键。在您的情况下 var obj = { helloText: "Hello World!" }; var foo = obj; delete obj;,对象不会被删除。检查 obj。下一步,运行 delete obj.helloText,您可以看到 foo 现在指向一个空对象。"""

J
Jesse Rusak

delete 操作符只删除一个引用,而不是一个对象本身。如果它确实删除了对象本身,其他剩余的引用就会悬空,就像 C++ 删除一样。 (访问其中一个会导致崩溃。使它们全部变为空意味着在删除每个对象时需要额外的工作或额外的内存。)

由于 Javascript 是垃圾收集的,因此您不需要自己删除对象 - 当无法再引用它们时,它们将被删除。

如果您完成了对对象的引用,删除对它们的引用会很有用,因为这为垃圾收集器提供了更多关于可以回收的信息。如果对大对象的引用仍然存在,这可能会导致它未被回收——即使您的程序的其余部分实际上并未使用该对象。


delete 关键字仅适用于对象的属性,不适用于变量。 perfectionkills.com/understanding-delete
@AlexJM 是的,Guffa 的下一个答案(及其评论)对此进行了详细讨论。
一个对象的属性可以是另一个对象。例如; var obj = {a: {}}; delete obj.a;
但是...不是变量实际上是 window 的属性吗?
@Soaku 不是局部变量。 (例如用 var 声明的那些)
G
Guffa

delete 命令对常规变量没有影响,只有属性。在 delete 命令之后,该属性没有值 null,它根本不存在。

如果属性是对象引用,delete 命令会删除属性而不是对象。如果对象没有其他引用,垃圾收集器将处理该对象。

例子:

var x = new Object();
x.y = 42;

alert(x.y); // shows '42'

delete x; // no effect
alert(x.y); // still shows '42'

delete x.y; // deletes the property
alert(x.y); // shows 'undefined'

(在 Firefox 中测试。)


如果这是在全局范围内执行的,您的 x 变量将成为全局 window 对象上的一个属性,并且 delete x; 确实会完全删除 x 变量。
@crescentfresh:如果它是隐式声明的,它只是一个属性。如果它像示例中那样显式声明,它是一个全局变量,不能被删除。
@Tarynn:我明白了,这就是问题所在。如果您在控制台中执行此操作,出于某种原因,x 在某些浏览器中将不是正确的变量,而是 window 对象中的属性。这当然是控制台的问题,并不能反映代码的正常执行方式。
@Guffa 经过大量研究后,我不得不承认,我没有足够的代表否决投票可能是件好事。我最诚挚的歉意,并感谢您花时间向我展示发生了什么...这是一个深入的解释:perfectionkills.com/understanding-delete/#firebug_confusion
@chao:我明白了。你和 Tarynn 有同样的问题(见前面的评论)。当您在控制台中执行此操作时,它与实际代码中的工作方式不同。
A
Alex

“隐式声明的变量”是全局对象的属性,因此 delete 对它们起作用,就像它对任何属性起作用一样。用 var 声明的变量是坚不可摧的。


我从来没有意识到 var 如此糟糕。
这是一个很好的观点,也是一个 JS 陷阱。人们习惯于删除窗口变量,然后想知道为什么他们不能对局部变量做同样的事情。
let 也是如此。
D
David Ackerman

来自 Mozilla 文档,“您可以使用 delete 运算符删除隐式声明的变量,但不能删除使用 var 语句声明的变量。”

这是链接:https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference:Operators:Special_Operators:delete_Operator


D
Derlin

delete 不用于删除 java Script 中的对象。

delete 用于在您的情况下删除 object key

var obj = { helloText: "Hello World!" }; 
var foo = obj;
delete obj;

对象未删除检查 obj 仍然采用相同的值删除用法:

delete obj.helloText

然后检查 obj, foo,两者都是空对象。


P
Pedro Justo

将变量设置为 null 可确保中断所有浏览器中对对象的任何引用,包括在 DOM 元素和 Javascript 范围之间进行的循环引用。通过使用 delete 命令,我们将对象标记为在下次运行垃圾收集时清除,但如果有多个变量引用同一个对象,删除单个变量不会释放对象,它只会删除之间的链接那个变量和对象。并且在垃圾收集的下一次运行中,只会清理变量。


g
garek

刚刚找到了一个您可能认为有趣的 jsperf。 (将其保留在周围以完成图片可能会很方便)

它比较删除、设置 null 和设置未定义。

但请记住,它会在您多次删除/设置属性时测试情况。


f
fgb

除了 GC 问题,为了性能,应该考虑浏览器可能在后台进行的优化 ->

http://coding.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-javascript/

似乎将引用设为空而不是删除它可能会更好,因为这可能会改变 Chrome 使用的幕后“类”。


j
johndhutcheson

IE 5 到 8 有一个错误,在宿主对象(窗口、全局、DOM 等)的属性上使用删除会引发 TypeError“对象不支持此操作”。

var el=document.getElementById("anElementId");
el.foo = {bar:"baz"};
try{
    delete el.foo;
}catch(){
    //alert("Curses, drats and double double damn!");
    el.foo=undefined; // a work around
}

稍后如果您需要检查属性在哪里具有完整值的含义,请使用 el.foo !== undefined,因为 "foo" in el 在 IE 中将始终返回 true。

如果你真的需要财产真正消失......

function hostProxy(host){
    if(host===null || host===undefined) return host;
    if(!"_hostProxy" in host){
       host._hostproxy={_host:host,prototype:host};
    }
    return host._hostproxy;
}
var el=hostProxy(document.getElementById("anElementId"));
el.foo = {bar:"baz"};

delete el.foo; // removing property if a non-host object

如果您需要将主机对象与主机 API 一起使用...

el.parent.removeChild(el._host);

C
Craig London

我在寻找同样的答案时偶然发现了这篇文章。我最终做的只是弹出 obj.pop() 我对象中所有存储的值/对象,以便我可以重用该对象。不确定这是否是不好的做法。这种技术对我在 Chrome 开发工具或 FireFox Web 控制台中测试我的代码非常有用。


H
Hank

这对我有用,虽然它不是一个好习惯。它只是删除对象所属的所有关联元素。

 for (element in homeService) {
          delete homeService[element];
  }

什么是最佳实践?我记得读到删除操作符对于删除对象属性并不是最有效的。我相信我在 Crockford 的 JavaScript 书中读到了这个,但目前无法挖掘它。