JavaScript作用域与作用域链

JavaScript作用域与作用域链

💡 原文中文,约4400字,阅读约需11分钟。
📝

内容提要

本文讨论了JavaScript中的作用域和变量声明,强调内层函数对外层变量的访问,以及`let`和`var`的区别。通过示例说明了作用域链和变量提升的概念,以及不同作用域中变量的可见性和生命周期。

🔎

延伸解读

var 与 let 的作用域差异

var 声明的变量仅受函数作用域限制,在 if 等块中声明会泄漏到外层;let 则具有块级作用域,仅在最近的 {} 内有效。此外,var 允许重复声明,而 let 在同一作用域内重复声明会抛出语法错误。理解这些差异有助于避免变量污染和意外覆盖。

变量提升的实际影响

var 声明的变量会被提升到函数顶部,但赋值留在原地,因此可能在赋值前访问得到 undefined。let 虽然也有提升,但存在暂时性死区,在声明前访问会抛出 ReferenceError。这要求开发者注意声明顺序,减少因提升导致的隐蔽错误。

作用域链与自由变量查找

当函数内访问一个非自身或全局的变量(自由变量)时,会沿作用域链向外层逐级查找,直到全局作用域。例如内层函数可以访问外层函数的变量,但外层不能访问内层的。这种机制决定了变量的可见性,也解释了闭包如何捕获外部变量。

循环中 var 与 let 的经典陷阱

使用 var 在 for 循环中绑定事件时,所有回调共享同一个变量 i,导致点击时输出相同的最终值。改用 let 后,每次迭代都会创建一个新的块级作用域变量,回调能正确捕获当前值。这是块级作用域解决实际问题的典型例子。

❓

Q&A

JavaScript中的作用域链是什么?

作用域链是指内层函数可以访问外层函数的变量,从而形成的变量访问链。

var和let的主要区别是什么?

使用var声明的变量会提升到函数顶部,而let声明的变量在块级作用域内有效,不会提升。

if语句块会创建新的作用域吗?

不会,if语句块不会创建新的作用域,变量依然在全局作用域中。

在同一作用域内可以重复声明同名变量吗?

不可以,使用let声明的变量在同一作用域内不能重复声明同名变量,否则会导致语法错误。

自由变量在函数中如何访问?

自由变量可以通过作用域链访问外层变量。

let声明的变量在什么情况下不可用?

let声明的变量在超出其块级作用域后不可用。

🏷️

标签

➡️

继续阅读