萌新,请问下,为什么下面这段代码,会导致内存堆积
发布于 7 年前 作者 AikenL 4193 次浏览 来自 问答

RT.

var o = null

function replaceObject() {
  let n = o
  o = {
    arr: new Array(100000)
  }
  o.fn = function() {
    console.log(n)
  }
}

var num = 100 // 加大 num 不能释放的内存越多
for (let i = 0; i < num; i++) {
  replaceObject()
}

下面这种写法,就不会

var o = null
var z = null

function replaceObject() {
  let n = o

  o = {
    arr: new Array(100000)
  }

  z = {
    fn() {
      console.log(n)
    }
  }
}

var num = 100 // 加大 num 不会堆积内存
for (let i = 0; i < num; i++) {
  replaceObject()
}
8 回复

node - v6.10.2 node - v8.7.0 以上效果一样

顶下,求解中。

区别在于,一个闭包了原先的自己,一个闭包了原先的别人

盲区,结果论是如此。就结果来说,一个能从标记清除的根里找回内存引用,一个不能找到,所以前者堆积,后者被释放

上面的情况

// 第一次replaceObject
let n = o // 此时是null
o = { // 第一个o,暂且称为o1
  arr: new Array(100000)
}
o.fn = function() {
  console.log(n) // 这个n是null,没问题
} 
  
// 第二次replaceObject

let n = o // 此时是o1
o = {     // 第二个o,暂且称为o2
  arr: new Array(100000)
}
o.fn = function() {
  console.log(n) // 这个n是o1,显然只要o2存在,则o1不应被回收
} 
// ...接下来继续
// o3将引用o2,导致o2无法回收,o4引用o3......

下面的情况自己应该就能想明白了吧

@dislido引用论解释的话,那这种情况也说的通了。

var o = null

function replaceObject() {
  let n = o

  function bn() {
    console.log(n)
  }

  o = {
    arr: new Array(100000),
    fn() {
	  // 与 bn 共享作用域,bn 引用了老的 n,同上引用论解释
      console.log('')
    }
  }
}

var num = 100 // 加大 num 不能释放的内存越多
for (let i = 0; i < num; i++) {
  replaceObject()
}

因为两个函数在同一个作用域里,一个产生全局闭包,另一个无引用,但是他们的作用域共享,导致一样的结果

meteor.js 发现的问题的解释了。

@dislido @Kyoloro

有道理,暂且这样理解,来规避出现的风险

第一段代码循环引用了,@dislido 讲的很好 第二段代码,变量 z,每次都会清空,就不会内存泄漏。

回到顶部