setTimeout 形成闭包问题
操作步骤
尝试分别在两秒内点击两按钮
问题
- 下列代码输出结果是什么?
- 为什么?
<button id="btn">Click</button>
<button id="btn2">Click2</button>
<script>
// 尝试分别在两秒内点击两按钮
function test() {
var count = 1
return function () {
setTimeout(() => {
count++
console.log(count)
}, 2000)
}
}
function test2() {
var count = 1
setTimeout(function () {
count++
console.log(count)
}, 2000)
}
document.getElementById('btn').onclick = test()
document.getElementById('btn2').onclick = function () {
test2()
}
</script>
结果
Click 按钮两秒内点击三次情况。
Click2 按钮两秒内点击三次情况。
个人理解及疑惑
Click按钮
两秒内点击三次,输出结果为 2,3,4
,这个是因为形成闭包,被外部引用,所以不会被 v8 的垃圾回收机制回收,自然 count
值也会被保存下来。
主要有疑问是 Click2按钮
, 为什么会输出结果为 2, 2, 2
,在我的理解,var
定义变量有变量提升作用,所以每次 setTimeout
会改变函数 test2
作用域内的 count
值,所以理想结果应该为 2, 3, 4
。
欢迎各路大佬来解答, 小弟先谢为敬。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
btn2值为一个匿名函数每次点击调用, 函数内部调用
test2
但是没有储存test2
的引用, 那么test2
执行完成之后就会被垃圾回收机制回收, 其实每次执行test2
都重新创建了count
变量并赋值为1test2 每次执行都重新定义了一个 该函数内部作用域内的 新的 count 1
这里会执行一次test();以后你每次点击都是执行return function(){...}这个函数,这里面的count是闭包引用。
而这个,每次点击都是执行test2();count被初始化了。
首先这里没有出现变量提升,而是用到了作用域链,function在声明的时候会创建自己的上下文,setTimeout里面的回调只是引用了上一层作用域链中的变量