变量、作用域、闭包
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
其原因有两点:
- setTimeout 是一个任务,将在 for 所有循环完成之后执行;
- i 由 var 定义:所有的 setTimeout 实际上都引用了“相同作用域里的同一个 i” —— 而它在所有循环之后其值为 10;
要与预期输出一致,有两种方式:
- 通过使用“立即执行的函数表达式”来捕获 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) }
- 使用 let 替换 var:
for (let i = 0; i < 10; i++) { (function(i) { setTimeout(function() { console.log(i) }, 100 * i) })(i) }
var作用域或函数作用域 当用let声明一个变量,它使用的是词法作用域或块作用域。