一段存在内存泄漏的JS代码,求解释 谢谢
发布于 8 年前 作者 AirccGit 4372 次浏览 来自 问答

一篇介绍Node垃圾回收机制的文章中,举了一段如下代码的示例来说明内存泄漏,望社区哪位朋友帮忙详细的解释一下啊!谢谢

var theThing = null
var replaceThing = function () {
  var originalThing = theThing
  var unused = function () {
    if (originalThing)
      console.log("hi")
  }
  theThing = {
    longStr: new Array(1000000).join('*'),
    someMethod: function () {
      console.log('someMessage')
    }
  };
};
setInterval(replaceThing, 1)

原文章链接

8 回复

你可以在命令行试下 new Array(1000000).join('*') 就知道了,资源只声明不释放再加上死循环,肯定内存泄漏

@fyibmsd 内存泄漏肯定是声明的资源没有释放。但这段代码的关键应该是 unused 这个 function 中引用了外部对象 originalThing 形成闭包,引起词汇作用域问题。如果注释掉 unused 这个 function,在 node 下跑好像是木有问题的,但是吧~我还是不能很明白的解释这个问题。

@AirccGit 你都自己回答自己了,还木有明白?通常闭包有几个好处,可以达到惰性求值的效果,还有个作用闭包作用域内的变量不会被gc回收,所以可以拿来模拟私有变量,或者希望变量常驻内存,或者避免全局变量污染,如果你看过之前node的require和module机制的话,应该还记得每一个node module就是一个个 function(){……return function(……)}() 这样的结构,真是利用了闭包的有点让模块常驻内存,你非要把这个优点当缺点用当然有问题了,比如 你新建一个a.js 里面放这段代码: module.exports=new Array(10000000).join(*) 然后你统计目录下新建一个问价b.js 写这么一段代码:var a=require(’./a6’); require(‘http’).createServer().listen(8888) 然后run起来,依然内存泄露,你的模块a文件永远常驻内存.不知我这么说你明白木有

同级目录,不是统计目录,打错了抱歉噢

@fantasticsoul Thanks! 本质上我是不太理解 作用闭包作用域内的变量不会被gc回收, 如果 unused 对象不是 Function 而是一个普通对象的话,gc会回收掉 就不存在内存泄漏这个问题了。

难道未引用的闭包不会释放的吗

回到顶部