变量、作用域、闭包

来自Wikioe
Eijux讨论 | 贡献2023年4月15日 (六) 18:38的版本 (创建页面,内容为“category:JavaScript == 变量 == === 词法作用域 === == 闭包 == == <span style="color: green">'''一个有意思的例子'''</span> == 一个涉及到“Event Loop”和“var 作用域”的例子。 对于以下代码: : <syntaxhighlight lang="JavaScript" highlight=""> for (var i = 0; i < 10; i++) { setTimeout(function() { console.log(i) }, 100 * i) } </syntaxhighlight> : 是否预期输出: : <syntaxhighlight lang="bash"…”)
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)
跳到导航 跳到搜索


变量

词法作用域

闭包

一个有意思的例子

一个涉及到“Event Loop”和“var 作用域”的例子。

对于以下代码:

for (var i = 0; i < 10; i++) {
    setTimeout(function() { console.log(i) }, 100 * i)
}
是否预期输出:
0
1
2
3
4
5
6
7
8
9
但,实际输出:
10
10
10
10
10
10
10
10
10
10

其原因有两点:

  1. setTimeout 是一个任务,将在 for 所有循环完成之后执行;
  2. i 由 var 定义:所有的 setTimeout 实际上都引用了“相同作用域里的同一个 i” —— 而它在所有循环之后其值为 10;

要与预期输出一致,有两种方式:

  1. 通过使用“立即执行的函数表达式”来捕获 i:
    for (var i = 0; i < 10; i++) {
        (function(i) {
            setTimeout(function() { console.log(i) }, 100 * i)
        })(i)
    }
    
    • 不能妄想通过 let、const 来捕获:
      for (var i = 0; i < 10; i++) {
          setTimeout(function() { const v = i; console.log(i); }, 100 * i)
      }
      
  2. 使用 let 替换 var
    for (let i = 0; i < 10; i++) {
        (function(i) {
            setTimeout(function() { console.log(i) }, 100 * i)
        })(i)
    }
    
var作用域或函数作用域

当用let声明一个变量,它使用的是词法作用域或块作用域。