回调函数内部声明的变量是否保留在内存中,还是在回调执行结束时销毁?

Do variables declared inside callback functions remain in memory or are they destroyed upon end of callback execution?

本文关键字:回调 执行 结束 内存 声明 内部 函数 变量 保留 是否      更新时间:2023-09-26

我有这个代码片段;它基本上连接到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

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

在您的示例中,var msg不会在其原始作用域之外"泄漏",因此当回调完成它的工作时,它很可能会被销毁。
有一件事要注意——这个对象的销毁不必立即发生——JS引擎大多是垃圾收集的,所以这片内存可以在堆栈上停留一段时间,但它将不再是可访问的。

如果你在外部作用域中声明这个变量,如果这个作用域在内存中,它可能会留在内存中(所以,其他代码段可以访问该变量)。您可以在MDN的闭包部分中了解此行为。

另一个需要注意的是console.log的使用。通常,非原语值(如对象或数组,它们实际上是"特殊"对象)可以通过引用访问,而不是通过值访问。因此,如果您的var msg是一个非原语,那么它很可能会一直保存在内存中,直到您清空控制台。原始值将被复制,因此严格地说,它们仍然会保存在内存中,但可能会在内存的另一个地方(尽管JIT引擎可能会尝试优化这一点,并且在不必要的情况下不复制内存)。

Node.js(和所有javascript引擎)依赖于跟踪垃圾收集,这意味着已分配的内存以不确定的方式被释放,即您无法准确预测何时会发生。这通常不会影响到您,但是如果您确实希望以可预测的方式释放一些内存块或其他资源,则必须使用一些特殊的技术。

在您的特定示例中,'msg'将被删除,但不要期望它立即被删除。