在本教程中,您将了解 JavaScript 变量提升及其背后的工作原理。
JavaScript 变量提升简介
当 JavaScript 引擎执行 JavaScript 代码时,它会创建全局执行上下文。全局执行上下文有两个阶段:
- 创建
- 执行
在创建阶段,JavaScript 引擎将变量和函数声明移动到代码的顶部。这在 JavaScript 称为变量提升。
变量提升
变量提升意味着 JavaScript 引擎将变量声明移动到脚本的顶部。例如,下面的示例声明 counter
变量并将其值初始化为 1
:
console.log(counter); // 👉 undefined
var counter = 1;
在这个例子中,我们在声明之前引用 counter
变量。
但是,第一行代码不会导致错误。原因是 JavaScript 引擎将变量声明移动到脚本的顶部。
从技术上讲,代码在执行阶段看起来如下所示:
var counter;
console.log(counter); // 👉 undefined
counter = 1;
在全局执行上下文的创建阶段,JavaScript 引擎将 counter
变量放入内存并将其值初始化为 undefined
.
let 关键字
下面用 let
关键字声明 counter
变量:
console.log(counter);
let counter = 1;
JavaScript 将会抛出下面的错误:
"ReferenceError: Cannot access 'counter' before initialization
错误信息说明 counter
变量已经在堆内存中。但是,它还没有被初始化。
在幕后,JavaScript 引擎会提升使用let
关键字声明的变量。但是,它不会初始化 let
声明的变量。
请注意,如果您访问一个不存在的变量,JavaScript 将抛出一个不同的错误:
console.log(alien);
let counter = 1;
这是错误:
"ReferenceError: alien is not defined
函数提升
与变量一样,JavaScript 引擎也会提升函数声明。这意味着 JavaScript 引擎还将函数声明移动到脚本的顶部。例如:
let x = 20,
y = 10;
let result = add(x, y);
console.log(result); // 👉 30
function add(a, b) {
return a + b;
}
输出:
30
在这个例子中,我们在定义 add()
函数之前调用 add()
函数。上面的代码等同于以下代码:
function add(a, b){
return a + b;
}
let x = 20,
y = 10;
let result = add(x,y);
console.log(result); // 👉 30
在上下文的创建阶段,JavaScript 引擎将 add()
函数声明放在堆内存中。准确地说,JavaScript 引擎创建一个 Function
类型的对象和一个引用 add
函数对象的函数引用。
函数表达式
以下示例将 add
函数由普通函数更改为函数表达式:
let x = 20,
y = 10;
let result = add(x,y); // ❌ Uncaught ReferenceError: add is not defined
console.log(result);
let add = function(x, y) {
return x + y;
}
如果执行代码,会出现如下错误:
Uncaught ReferenceError: add is not defined
在全局执行上下文的创建阶段,JavaScript 引擎在内存中创建 add
变量并将其值初始化为 undefined
。
执行以下代码时,add
是 undefined
,因此,它不是函数:
let result = add(x,y);
仅在全局执行上下文的执行阶段分配将匿名函数分配给 add
变量。
箭头函数
下面示例将 add
函数表达式更改为箭头函数:
let x = 20,
y = 10;
let result = add(x,y); // ❌ Uncaught ReferenceError: add is not defined
console.log(result);
let add = (x, y) => x + y;
该代码还抛出与函数表达式示例相同的错误,因为箭头函数是用于定义函数表达式的语法糖。
Uncaught ReferenceError: add is not defined
与函数表达式类似,箭头函数不会提升。
结论
JavaScript 提升发生在上下文的创建阶段,它将变量和函数声明移动到脚本的顶部。
JavaScript 引擎提升使用 let
关键字声明的变量,但不会将它们初始化。使用 var
关键字声明的变量也一样。
JavaScript 引擎不会提升函数表达式和箭头函数。