在这个陈旧的闭包中*实际上*发生了啥?

Posted

技术标签:

【中文标题】在这个陈旧的闭包中*实际上*发生了啥?【英文标题】:What is *actually* happening within this stale closure?在这个陈旧的闭包中*实际上*发生了什么? 【发布时间】:2022-01-23 07:55:39 【问题描述】:

我觉得我对闭包的了解几乎在那里,但我正在努力理解为什么第一个代码 sn-p 记录 0(是一个陈旧的闭包)但是,第二个代码sn-p 工作并记录更新的值..

这是某种参考问题吗?

在第一个例子中,我们是不是没有跟踪 count 的引用,只将它的初始值赋给 message?

通过在 log 函数中移动 message 变量,我们是否以某种方式告诉 JS 跟踪计数值的引用?

function createIncrement() 
  let count = 0;

  function increment() 
    count++;
  

  let message = count;
  function log() 
    console.log(message);
  

  return [increment, log];


const [increment, log] = createIncrement();

increment();
log();

// this will log 0

function createIncrement() 
  let count = 0;

  function increment() 
    count++;
  

  function log() 
    let message = count;
    console.log(message);
  

  return [increment, log];


const [increment, log] = createIncrement();

increment();
log();

// this will log 1

【问题讨论】:

"在第一个示例中,我们是否没有跟踪 count 的引用,而只将其初始值分配给 message?" - 是的。闭包跟踪message的引用,它只有count的初始值,但不会被log闭包更新。 【参考方案1】:

在第一个例子中,我们是不是没有跟踪 count 的引用,而只是将它的初始值赋给 message? 通过在 log 函数中移动 message 变量,我们是否以某种方式告诉 JS 跟踪计数值的引用?

这就是你正在努力解决的问题。让我们尝试分解那里发生的事情。

它的核心就是这样:

let count = 0;
let message = count;
console.log(message);
count++; // it's exactly the same as count = count + 1;
console.log(message); // still prints 0

这与闭包无关,而与数字作为不可变值有关。当我们增加count 时,我们为变量分配了一个值为 1 的数字的新实例。 message 仍然指向旧实例(值,在这种情况下它是相同的),因此日志将打印相同的旧值。

如果我正确理解了您的误解(!),您认为count 是一个可以在其中插入数值的容器,这有点错误。

它是一个指向数字和不可变值的指针,它位于内存中的某个位置。当您执行 message = count 时,您确保 message 和 count 指向相同的内存地址,其中包含 0

当您编写count++ 时,您正在内存中某处为数字1 分配一个新数字,而count 现在指向新对象。 message 不受此操作的影响。 这是我认为不是很清楚的关键部分

在您的第二个示例中,message 在您每次登录时都会重新分配,因此它将始终包含对正确值的引用。

【讨论】:

这正是我需要的,谢谢! 我刚刚编辑了答案以更好地解释内存寻址。

以上是关于在这个陈旧的闭包中*实际上*发生了啥?的主要内容,如果未能解决你的问题,请参考以下文章

js_闭包

闭包深度理解

python闭包和装饰器

javascirpt的闭包理解

闭包中的变量捕获详解

在闭包中捕获结构引用不允许发生突变