Js 内存泄漏问题

发布于 2022-09-04 16:06:48 字数 971 浏览 22 评论 0

<html>

<body>
    <script type="text/javascript">
    document.write("Avoiding memory leak via closure by breaking the circular reference");
    window.onload = function outerFunction() {
      var obj = document.getElementById("element")
      obj.onclick = function innerFunction() {
        alert("Hi! I have avoided the leak");
        // Some logic here
      }
      obj.bigString = new Array(1000).join(new Array(1000).join("XXXXX"))
      obj = null //This breaks the circular reference
    }
    </script>
    <button id="element">Click Me</button>
</body>

</html>

https://www.ibm.com/developer... 这篇IBM 关于JS内存泄漏的文章中,提到 DOM 与 JS 对象 obj 存在循环引用。为什么这两者存在相互引用呢?另外,文中也提到解决方法:obj = null 打破循环引用。为什么我在 Chrome 的 Profile 中,无论 obj = null 是否存在这句,内存占用量是相等的,是否说明这句无效,依然存在内存泄漏呢?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

北城半夏 2022-09-11 16:06:48

DOM与obj 循环引用 楼主你先要明白 id为element的这个元素和obj的关系 如果没有定义obj这个变量 那这个dom节点就不存在了吗?

obj=null只是把obj这个对节点的引用去掉了 这个元素本身还是存在的啊 所以内存当然没有变化

楼主你调用一下obj.remove() 把节点从dom树里删除 就看出区别了 不过可能数据量太小不明显

书信已泛黄 2022-09-11 16:06:48

首先这篇文章是2007年的时候,所以提到的很多方式在现代浏览器中已经不存在了。

JavaScript垃圾回收最常用的是引用计数标记清除Mark-and-sweep

引用计数

对象有没有其他对象引用到它。

对于 onclick = function 而言,由于受词法环境的影响,会在外部函数里引用DOM,会被标记至少一次引用。

obj.bigString 引用了一个数组,即使你把DOM移除,垃圾回收也无法对 obj.bigString 内存回收。

标记清除 Mark-and-sweep

标记:指垃圾回收开始时会从 window 全局对象开始,找出所有引用的对象,对未引用的进行标记。

清除:就是删除标记的引用。

示例中的内存泄露

如果你的示例放在IE67下面会引起泄露,这是它使用的是引用计数垃圾回收机制。

这也就是说为什么需要手工调用 obj=null 解除引用 。

而这个示例如果放在现代浏览器中,是不会产生循环引用的。因为对于DOM及其相关事件而言,如果无法从 window 中被获取到的话,都会被垃圾回收器回收。

一些细节

1、无意的全局变量

function fn() {
    a = 1;
}
fu();

执行 fn 时会创建一个作用域,执行完毕后,原则上在这个作用域内声明的变量都会被标识可清除;可 a 由于是全局变量倒置无法被回收。

所以,对于这类型的变量,并且是数据量很大的情况下,手工设置为 a = null 应该有些解决变量内存回收。

2、减少对象创建也能改善内存垃圾

比如 arr = [],实际上是把原来的数组当成垃圾,然后创建一个新的数组。最好的最好是 arr.length = 0 这样不会创建新数组对象。

黎歌 2022-09-11 16:06:48

闭包。 会导致内部引用外部变量无法被回收导致内存泄露,现在的浏览器都有优化机制,所有你看不出来效果的,题主应该没按顺序看完全文吧,全文讲的挺细的。

补充:至于你说的为什么循环引用,是因为window.onload是在对象装载进DOM后触发,DOM引用了obj,而obj又是从getElementsById获取的。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文