JavaScript 变量提升 (Hoisting)
变量提升是 JavaScript 的默认行为,它会将声明移动到顶部。
JavaScript 声明会被提升
在 JavaScript 中,变量可以在声明之后使用。
换句话说,变量可以在声明之前使用。
示例 1 和 示例 2 的结果相同
示例 1
x = 5; // 给 x 赋值 5
elem = document.getElementById("demo"); // 找到一个元素
elem.innerHTML = x; // 在元素中显示 x
var x; // 声明 x
自己动手试一试 »
示例 2
var x; // 声明 x
x = 5; // 给 x 赋值 5
elem = document.getElementById("demo"); // 找到一个元素
elem.innerHTML = x; // 在元素中显示 x
自己动手试一试 »
要理解这一点,您必须理解“变量提升”这个术语。
变量提升是 JavaScript 的默认行为,它会将所有声明移动到当前作用域的顶部(当前脚本或当前函数的顶部)。
let 和 const 关键字
使用 let
和 const
定义的变量会被提升到块的顶部,但不会被 *初始化*。
这意味着:代码块知道该变量,但在声明之前无法使用它。
在声明之前使用 let
变量会导致 ReferenceError
。
变量处于“暂时性死区”(temporal dead zone),从代码块开始直到声明之前。
在声明之前使用 const
变量会导致语法错误,因此代码根本不会运行。
在 JS Let / Const 中阅读更多关于 let 和 const 的信息。
JavaScript 初始化不会被提升
JavaScript 只提升声明,而不提升初始化。
示例 1 与 示例 2 的结果不相同
示例 1
var x = 5; // 初始化 x
var y = 7; // 初始化 y
elem = document.getElementById("demo"); // 找到一个元素
elem.innerHTML = x + " " + y; // 显示 x 和 y
自己动手试一试 »
示例 2
var x = 5; // 初始化 x
elem = document.getElementById("demo"); // 找到一个元素
elem.innerHTML = x + " " + y; // 显示 x 和 y
var y = 7; // 初始化 y
自己动手试一试 »
最后一个示例中 y 是 undefined,这是否合乎情理?
这是因为只有声明(var y)被提升到顶部,而不是初始化(=7)。
由于变量提升,y 在使用之前已经被声明,但由于初始化没有被提升,所以 y 的值是 undefined。
示例 2 等同于以下写法
示例
var x = 5; // 初始化 x
var y; // 声明 y
elem = document.getElementById("demo"); // 找到一个元素
elem.innerHTML = x + " " + y; // 显示 x 和 y
y = 7; // 给 y 赋值 7
自己动手试一试 »
在顶部声明您的变量!
变量提升是(许多开发者)不知道或忽略的 JavaScript 行为。
如果开发者不理解变量提升,程序可能会包含 bug(错误)。
为避免 bug,请始终在每个作用域的开头声明所有变量。
由于 JavaScript 以这种方式解析代码,所以这始终是一个好规则。
JavaScript 的严格模式不允许使用未声明的变量。
在下一章中学习 "use strict"。