setTimeout 形成闭包问题

发布于 2022-09-12 03:33:33 字数 1284 浏览 19 评论 0

操作步骤

尝试分别在两秒内点击两按钮

问题

  • 下列代码输出结果是什么?
  • 为什么?

<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 按钮两秒内点击三次情况。

image.png

Click2 按钮两秒内点击三次情况。

image.png

个人理解及疑惑

Click按钮 两秒内点击三次,输出结果为 2,3,4 ,这个是因为形成闭包,被外部引用,所以不会被 v8 的垃圾回收机制回收,自然 count 值也会被保存下来。

主要有疑问是 Click2按钮 , 为什么会输出结果为 2, 2, 2,在我的理解,var 定义变量有变量提升作用,所以每次 setTimeout 会改变函数 test2 作用域内的 count 值,所以理想结果应该为 2, 3, 4

欢迎各路大佬来解答, 小弟先谢为敬。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

離殇 2022-09-19 03:33:33

btn2值为一个匿名函数每次点击调用, 函数内部调用test2但是没有储存test2的引用, 那么test2执行完成之后就会被垃圾回收机制回收, 其实每次执行test2都重新创建了count变量并赋值为1

伴随着你 2022-09-19 03:33:33

test2 每次执行都重新定义了一个 该函数内部作用域内的 新的 count 1

你穿错了嫁妆 2022-09-19 03:33:33
  document.getElementById('btn').onclick = test()

这里会执行一次test();以后你每次点击都是执行return function(){...}这个函数,这里面的count是闭包引用。

 document.getElementById('btn2').onclick = function () {
    test2()
  }

而这个,每次点击都是执行test2();count被初始化了。

心的位置 2022-09-19 03:33:33

首先这里没有出现变量提升,而是用到了作用域链,function在声明的时候会创建自己的上下文,setTimeout里面的回调只是引用了上一层作用域链中的变量

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文