【问题标题】:Deleting Objects in JavaScript在 JavaScript 中删除对象
【发布时间】:2010-10-19 01:29:45
【问题描述】:

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

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

var foo = obj;

delete obj;

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

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

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

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

【问题讨论】:

  • 全文删除关键字webcache.googleusercontent.com/…
  • @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现在指向一个空对象。"""

标签: javascript pointers object memory-management garbage-collection


【解决方案1】:

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

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

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

【讨论】:

  • delete 关键字仅适用于对象的属性,不适用于变量。 perfectionkills.com/understanding-delete
  • @AlexJM 是的,Guffa(及其 cmets)的下一个回答会详细讨论这个问题。
  • 一个对象的属性可以是另一个对象。例如; var obj = {a: {}}; delete obj.a;
  • 但是……变量实际上不是window的属性吗?
  • @Soaku 不是局部变量。 (例如用var 声明的那些)
【解决方案2】:

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 相同的问题(请参阅前面的 cmets)。当您在控制台中执行此操作时,它与实际代码中的工作方式不同。
【解决方案3】:

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

【讨论】:

  • 我从来没有意识到 var 这么牛逼。
  • 这是一个很好的观点,也是一个 JS 陷阱。人们习惯于删除窗口变量,然后想知道为什么他们不能对局部变量做同样的事情。
  • let 也是如此。
【解决方案4】:

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

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

【讨论】:

    【解决方案5】:

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

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

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

    对象没有被删除检查 obj 仍然取相同的值删除用法:

    delete obj.helloText
    

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

    【讨论】:

      【解决方案6】:

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

      【讨论】:

        【解决方案7】:

        刚刚找到一个jsperf,鉴于此问题,您可能会认为这很有趣。 (将其保留在周围以完成图片可能会很方便)

        比较delete、设置null和设置undefined

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

        【讨论】:

          【解决方案8】:

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

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

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

          【讨论】:

            【解决方案9】:

            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);
            

            【讨论】:

              【解决方案10】:

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

              【讨论】:

                【解决方案11】:

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

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

                【讨论】:

                • 什么是最佳实践?我记得读过删除操作符对于删除对象属性并不是最好的做法。我相信我在 Crockford 的 JavaScript 书中读到了这个,但目前无法挖掘它。
                猜你喜欢
                • 1970-01-01
                • 2017-06-19
                • 1970-01-01
                • 2017-01-23
                • 2013-07-03
                • 2016-12-20
                • 1970-01-01
                • 2011-07-04
                • 1970-01-01
                相关资源
                最近更新 更多