【问题标题】:Javascript + Knockout.js memory leak - How to make sure object is being destroyed?Javascript + Knockout.js 内存泄漏 - 如何确保对象被销毁?
【发布时间】:2014-06-18 00:54:13
【问题描述】:

我正在使用google's 3 Snapshot method 来查找页面上的内存泄漏。 页面在 Knockout.js 和 Jquery Mobile UI 上运行。 我已经缩小到内存泄漏的 div 之一。在每个快照之间,我正在运行此脚本以清除内存泄漏对象。

$('.paddedContentContainer').children().each(function(index,item){
console.log(item); 
$(item).off(); 
ko.cleanNode($(item)); 
$(item).remove();
item = null;
});

.paddedContentContainer 是泄漏对象的父级。
现在有趣的部分是我仍然可以在保留对象树中看到对象。在下面的屏幕截图中,您可以看到我正在过滤从快照 1 和 2 中保留的快照 3 中的对象,并且通过文本可以看到来自控制台的$0 在屏幕上的同一对象中(事件销售订单和... .)。

我假设 .off();.remove(); 不足以收集对象。
如何永久销毁对该对象的所有引用?

【问题讨论】:

    标签: javascript jquery memory knockout.js memory-leaks


    【解决方案1】:

    你看过这个帖子吗:How to destroy a DOM element with jQuery?

    卢克的回答似乎很有趣:

    如果你想彻底摧毁目标,你有几个 选项。首先,您可以按照描述从 DOM 中删除对象 以上...

    console.log($target); // jQuery 对象 $target.remove(); // 从 DOM 中删除目标 console.log($target); // $target 仍然 存在选项 1 - 然后用空的 jQuery 对象替换目标 (jQuery 1.4+)

    $目标 = $();控制台.log($target); // 空的 jQuery 对象 选项 2 - 或者完全删除该属性(如果您在其他地方引用它会导致错误)

    删除$目标;控制台.log($target); // 错误:$target 不是 定义

    也许你应该最后delete $(item)

    【讨论】:

    • 这是一个非常好的例子来销毁 Javascript 对象没有 DOM 元素 snag.gy/bngFD.jpg 在屏幕截图中你可以看到项目被删除,然后我自己在控制台中对其进行评估。
    • 我可以看到你在控制台中写了 $0。我是说你应该试试delete $0
    • $0 是在检查堆时从 Chrome 开发者工具中获取数据的特殊命令。
    • 尝试delete $(item) 有什么问题?正如 Metalstorm 所说,如果 DOM 对象仍然存在,那可能是因为它仍然被引用
    • 它不会被删除你可以在我发给你的截图中看到它。
    【解决方案2】:

    .remove() 只是从 DOM 中删除该元素,如果有任何东西仍在引用它(在您的代码中),它将不会被垃圾收集。

    编辑

    是的,.remove() 是从 DOM 中分离/删除它的正确方法,但它仍然保存在内存中,因为其他东西正在引用它(在本例中是淘汰赛的内部结构)。

    一种方法,也是我这样做的方法,是保留我在控件中创建的所有高级 DOM 元素的集合,然后有一个销毁函数循环这些元素并在它们上调用 .remove() 并分配他们给null

    例如(注意这是保存在每个控制对象中(没有泄漏的全局内容):

    var elements = 
    {
        'table' : $('#some_table'),
        'button' : $('#some_button')
    };
    
    
    function destroy()
    {
        for(var key in elements)
        {
            elements[key].remove();
            elements[key] = null;
        }
    }
    

    您可以通过淘汰赛采取这种方法。

    【讨论】:

    • 如何找到引用该元素的所有内容? .off() 应该删除所有事件处理程序,那么所有其他的东西呢?
    • 嗯,检查员可能有办法查看所有参考资料?其中一列/右键单击?
    • 哦,绝对的。我已经知道它手握对象(函数(){return c++ +d})是淘汰赛,我一定是错误地表达了自己。如何获得通用机制来摆脱对任何 DOM 元素的所有引用,必须有一种分离元素的方法。
    • 用可能的解决方案编辑了我的答案。
    【解决方案3】:

    仅为那些对knockout.js 引用删除感到满意的人添加答案。 这从对象树中删除了手边的<div>

     $('.paddedContentContainer').children().each(function(index,item){
         $(item).off(); 
         ko.removeNode(item);
         $(item).remove();
         item = null;
     });
    

    【讨论】:

    • 我认为这是错误的,将 item 设置为 none 不会影响淘汰赛内部持有的引用,看看这个:jsfiddle.net/jy3MK
    • @Metalstorm 不,它肯定会,而 clearNode() 不会。非常欢迎您亲自尝试。
    猜你喜欢
    • 1970-01-01
    • 2011-04-17
    • 1970-01-01
    • 2022-12-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-14
    • 2012-04-24
    • 1970-01-01
    相关资源
    最近更新 更多