我对JavaScript的delete
运算符感到困惑。请使用以下代码:
var obj = {
helloText: "Hello World!"
};
var foo = obj;
delete obj;
执行完这段代码后,obj
为null
,但foo
仍然引用与obj
完全相同的对象。我猜这个对象与foo
指向的对象相同。
这让我感到困惑,因为我期望写delete obj
删除obj
在内存中指向的对象 - 而不仅仅是变量obj
。
这是因为JavaScript的垃圾收集器正在保留/释放,所以如果我没有指向该对象的任何其他变量,将从内存中删除吗?
(顺便说一句,我的测试是在Safari 4中完成的。)
答案 0 :(得分:434)
删除操作符仅删除引用,而不删除对象本身。如果它确实删除了对象本身,那么其他剩余的引用将是悬空的,就像C ++删除一样。 (并且访问其中一个会导致崩溃。要使它们全部转为null将意味着在删除或为每个对象额外的内存时有额外的工作。)
由于Javascript是垃圾收集的,因此您无需自行删除对象 - 当无法再引用它们时,它们将被删除。
如果您已完成对象的删除,则删除对象的引用会很有用,因为这会为垃圾回收器提供有关可以回收的内容的更多信息。如果对大对象的引用仍然存在,这可能导致它无法回收 - 即使程序的其余部分实际上没有使用该对象。
答案 1 :(得分:155)
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中测试过。)
答案 2 :(得分:54)
“隐式声明的变量”是全局对象的属性,因此delete对它们起作用就像它适用于任何属性一样。用var声明的变量是坚不可摧的。
答案 3 :(得分:23)
来自Mozilla文档,“您可以使用delete运算符删除隐式声明的变量,但不能删除使用var语句声明的变量。”
答案 4 :(得分:6)
基于@Guffa的回答。我发现以下方法对我有用:
var obj = {
helloText: "Hello World!"
};
obj = null;
delete obj;
首先将obj设置为null
,删除了对它的所有引用,然后就可以完全删除它。
我没有在其他浏览器上测试它,但这适用于phonegap 1.7.0
答案 5 :(得分:4)
delete
不用于删除java Script中的对象。
delete
用于删除案例中的object key
var obj = { helloText: "Hello World!" };
var foo = obj;
delete obj;
对象未删除检查obj仍然采用相同的值删除用法:
delete obj.helloText
然后检查obj, foo
,两者都是空对象。
答案 6 :(得分:2)
除了GC问题,对于性能,我们应该考虑浏览器可能在后台进行的优化 - >
http://coding.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-javascript/
似乎取消引用可能比删除它更好,因为这可能会改变Chrome使用的幕后“类”。
答案 7 :(得分:2)
答案 8 :(得分:1)
IE 5到8有一个错误,即在主机对象(Window,Global,DOM等)的属性上使用delete会引发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);
答案 9 :(得分:0)
我在寻找同样的答案时偶然发现了这篇文章。我最终做的只是弹出obj.pop()
我对象中所有存储的值/对象,以便我可以重用该对象。不确定这是不好的做法。这种技术对我在Chrome Dev工具或FireFox Web控制台中测试代码非常方便。
答案 10 :(得分:0)
将变量设置为null
可确保破坏对所有浏览器中对象的任何引用,包括在DOM元素和Javascript范围之间进行循环引用。通过使用delete
命令,我们在下一次运行Garbage集合时标记要清除的对象,但是如果有多个变量引用同一个对象,则删除单个变量将不会释放该对象,它只会删除该变量与对象之间的联系。在下一次运行垃圾收集时,只会清除变量。
答案 11 :(得分:0)
这项工作对我来说虽然不是一个好习惯。它只是删除所有 对象所属的关联元素。
for (element in homeService) {
delete homeService[element];