【问题标题】:Do variables declared inside callback functions remain in memory or are they destroyed upon end of callback execution?在回调函数中声明的变量是保留在内存中还是在回调执行结束时被销毁?
【发布时间】:2017-01-11 09:15:55
【问题描述】:

我有这个代码 sn-p;它基本上连接到 mongo 数据库并遍历文档。在每次迭代中,它都会搜索对象的消息数组。它创建消息变量,然后循环遍历它。 回调函数中声明的变量(var msg)是保留在内存中还是在回调函数执行结束时被销毁?如果var msg实际上被声明为let msg,会有什么不同吗?有没有办法从内存中丢弃整个范围?

MongoClient.connect(mongoUrl, (err, db) => {
  assert.equal(null,err);
  var collection_data = db.collection('threadContents').find();
  collection_data.on('data', (doc) => {
    var msg = doc.messages;
    for (var variable in msg) {
      console.log(msg);
    }//forin(msg)
  });//collection_data.on
});//mongo.connect

【问题讨论】:

  • is it destroyed upon end of callback function execution? - 通常是这样,这真的取决于代码
  • @JaromandaX 我提供了示例代码 sn-p。否则,推荐在回调函数执行结束时强制销毁变量的方法是什么?
  • 哦,你问的是你的具体代码吗?你关心哪个变量?
  • @JaromandaX 有描述。在 on('data') 回调函数中,声明了 var msg。是毁了还是还留在记忆里?
  • @Kunok 没有闭包,所以它会在某个时候被 GC 处理,但是一旦你完成循环,最好将它与doc.messages (msg = null; doc.messages = null;) 一起取消。

标签: javascript node.js memory theory ram


【解决方案1】:

理论上 - 是的。
在实践中 - 并不是那么简单......

在您的示例中,var msg 不会“泄漏”到其原始范围之外,因此当回调完成其工作时,它很可能会被销毁。
需要注意的一点 - 这个对象的销毁不必立即发生 - JS 引擎主要是垃圾收集,所以这块内存可以在堆栈上保留一段时间,但它不会再被访问了。

如果您要在外部作用域中声明此变量,则如果该作用域保留在内存中,它可能会保留在内存中(因此,其他代码段可以访问该变量)。您可以在 MDN 的 Closures 部分了解此行为。

另外需要注意的是console.log 的用法。通常,非原始值(如对象或数组,它们实际上是“特殊”对象)将可以通过引用访问,而不是通过值访问。因此,如果您的 var msg 是非原始的,它很可能会一直存在于内存中,直到您清除控制台。原始值将被复制,因此严格来说它们仍会保留在内存中,但可能会保留在内存中的另一个位置(尽管 JIT 引擎可能会尝试优化它并且如果没有必要则不复制内存)。

【讨论】:

  • 当您说“清除您的控制台?”时,您到底是什么意思?
  • 当然点击控制台中的“清除”按钮 :)
  • 我实际上是从终端运行节点脚本,但没有这样的选项,这不是我想要依赖的东西,因为我试图为我的脚本使用尽可能少的 RAM,这需要做在不太强大的硬件上进行了一些非常繁重的工作,我将这些脚本作为 CRON 作业运行。
  • 在 Node 的情况下,您不必担心它,因为 Node 只是将值“打​​印”到屏幕/终端并忘记它。但是,如果您使用某种交互式节点检查器,则该值很可能会持续存在,因为您将能够仔细检查记录的值。
【解决方案2】:

在您的具体示例中,“msg”将被删除,但不要指望它会立即被删除。

【讨论】:

  • JavaScript 稍后会在哪个事件上删除它(不是马上)?
  • 我的意思是说什么时候会发生是不可预测的。
  • 有相关的文档吗?
  • 勾选以auth0.com/blog/…开头
【解决方案3】:

Node.js(和所有 javascript 引擎)依赖于tracing garbage collection,这意味着分配的内存以非确定性方式释放,即您无法准确预测它何时会发生。这通常不会影响您,但是如果您真的希望以可预测的方式释放一些内存或其他资源,则必须使用一些临时技术。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多