关于 js 闭包(stale closure)问题的疑惑?
网上看到如下两段代码:
function createIncrement(i) {
let value = 0;
function increment() {
value += i;
console.log(value);
const message = `Current value is ${value}`;
return function logValue() {
console.log(message);
};
}
return increment;
}
const inc = createIncrement(1);
const log = inc(); // 1
inc(); // 2
inc(); // 3
// Does not work!
log(); // "Current value is 1"
function createIncrementFixed(i) {
let value = 0;
function increment() {
value += i;
console.log(value);
return function logValue() {
const message = `Current value is ${value}`;
console.log(message);
};
}
return increment;
}
const inc = createIncrementFixed(1);
const log = inc(); // 1
inc(); // 2
inc(); // 3
// Works!
log(); // "Current value is 3"
第二段代码与第一段代码的唯一区别仅仅在于, 将message
变量移入了 logValue()
函数中, 似乎就能"正确"读取到value
的值
两端代码均存在嵌套的闭包, 我个人分析的时候比较困惑, 个人理解为: value
由于inc()
的调用应该是不断变化的, 而由于存在最顶端的createIncrement()
/createIncrementFixed()
这个函数造成的闭包, 所读取的 value 值应该总是最新的即为 3? 但是似乎和实际结果有些不太符合, 不知道哪里理解错了, 恳请知道的前辈能详细分析一下? 不胜感激!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
从下面几个部分分析:
第一个误区:
因此
value
只被声明了一次,而且是在 局部作用域(闭包中),所以后续的访问都是同一个地方而
message
虽然也在局部作用域中,但是每次都被重新声明(而不是重新赋值);所以语法上看是 logValue 里面的 使用的是同一个,但是其实内存中不是同一个;因此 第一种写法,log 执行但结果都是当时 inc()执行时的值第二个误区:
在第二种写法中不仅仅是代码的位置发生了变化,同时值的引用也发生了变化; 当你任何时候执行
log
时,他都是访问value
的值而和message
没关系了,然而我们之前说了 value 会不断被重新赋值,因此log
每次执行都是拿到最新的。第三 换个写法实现,让message 也只声明一次,代码如下
这个时候 任何时候执行 log 也是一样 拿到最新的值
希望对你有帮助