NodeJS 内存泄漏:什么归类为闭包中的引用

问题描述 投票:0回答:1

我知道在某些情况下,如果闭包中存在引用,对象可以避免垃圾收集。

引用是否意味着需要将对象的引用分配给某物?或者调用/获取对象的属性也算作引用吗?

例如,以下内部函数会在闭包中创建对对象的引用吗?

const someObject = {
  myProp: 123, 
  callable: () => console.log('hello!')
}

function outer() {
  const innerAssign = () => {
     const innerVar = someObject.myProp;  // does this create reference in closure?
  }

  const innerCall = () => {
     someObject.callable();  // does this create reference in closure?
  }

  const innerRef = () => {
    const newRef = someObject;  // this surely creates a reference in closure
  }
}

此外,创建/使用对象属性的键数组是否会创建对原始对象的引用?

例如

const keys = Object.keys(someObject);

另一个问题:当在新范围内创建另一个对现有对象的引用时,会在堆上为该对象分配额外的内存——这是正确的吗?

node.js memory-leaks closures
1个回答
1
投票

此外,创建/使用对象属性的键数组是否会创建对原始对象的引用?

不,它没有。对象键本身只是独立的字符串或符号。他们对他们来自的对象没有任何参考。

问题的其他部分是指对象方法中使用的对象属性。属性永远不会独立于它们所在的对象而被垃圾回收。因此,这里重要的是谁拥有对对象本身的引用。由于在没有人引用对象的情况下无法调用方法,因此通常会为您处理事情。如果没有人引用该对象,那么就没有人可以调用它的任何方法,因此该对象可用于 GC。如果有人引用了这个对象,那么它就不会被 GC。

所以(1)如果一个对象的属性被分配给一个闭包中的变量,它不会创建一个对象的引用,并且(2)如果一个对象的方法在闭包中被调用,它会创建一个对对象的引用。这是正确的吗?

好吧,这取决于。您的代码是一个人为的示例,因为尽管您定义了三个内部函数,但没有任何代码真正调用过它们,因此引擎可能足够聪明以完全忽略它们,因为优化器可以完全删除它们。如果它们是可调用的,那么只要它们是可调用的,就不能进行 GC,因为所有内部函数都包含对

someObject
的引用。因此,只要可以调用任何内部函数并且可以访问,
someObject
就不能被 GC。

三个不同的内部函数都引用了

someObject
所以他们用它做不同的事情并不重要。能调用的都是一个参考

另一个问题:当在新范围内创建另一个对现有对象的引用时,会在堆上为该对象分配额外的内存——这是正确的吗?

由于您没有显示具体的代码示例,因此您的意思并不完全清楚。如果您在分配了

someObject
的新范围内创建变量,那么分配的唯一新内存就是变量本身。该变量包含指向
someObject
的一个副本的指针。没有单独的
someObject
副本只是因为在其他范围内对它有另一个引用。

© www.soinside.com 2019 - 2024. All rights reserved.