摘要:在本教程中,您将学习 JavaScript 提升的概念以及它在幕后的工作原理。
JavaScript 提升简介
当 JavaScript 引擎执行 JavaScript 代码时,它会创建 全局执行上下文。全局执行上下文有两个阶段:
- 创建
- 执行
在创建阶段,JavaScript 引擎会将变量和函数声明移至代码的顶部。这被称为 JavaScript 中的提升。
变量提升
变量提升意味着 JavaScript 引擎会将 变量声明 移至脚本的顶部。例如,以下示例声明了 counter
变量并将它的值初始化为 1
console.log(counter); // 👉 undefined
var counter = 1;
Code language: JavaScript (javascript)
在这个例子中,我们是在声明之前引用 counter
变量。
然而,第一行代码不会导致错误。原因是 JavaScript 引擎会将变量声明移至脚本的顶部。
从技术上讲,代码在执行阶段看起来像下面这样:
var counter;
console.log(counter); // 👉 undefined
counter = 1;
Code language: JavaScript (javascript)
在全局执行上下文的创建阶段,JavaScript 引擎会将 counter
变量放置在内存中,并将它的值初始化为 undefined
。
let 关键字
以下代码使用 let
关键字声明 counter
变量:
console.log(counter);
let counter = 1;
Code language: JavaScript (javascript)
JavaScript 会发出以下错误:
"ReferenceError: Cannot access 'counter' before initialization
错误消息说明 counter
变量已存在于堆内存中。但是,它还没有被初始化。
在幕后,JavaScript 引擎会提升使用 let
关键字声明的变量声明。但是,它不会初始化 let
变量。
请注意,如果您访问一个不存在的变量,JavaScript 会抛出一个不同的错误:
console.log(alien);
let counter = 1;
Code language: JavaScript (javascript)
这是错误信息:
"ReferenceError: alien is not defined
Code language: plaintext (plaintext)
函数提升
与变量类似,JavaScript 引擎也会提升 函数 声明。这意味着 JavaScript 引擎也会将函数声明移至脚本的顶部。例如:
let x = 20,
y = 10;
let result = add(x, y);
console.log(result); // 👉 30
function add(a, b) {
return a + b;
}
Code language: JavaScript (javascript)
输出
30
在这个例子中,我们在定义 add()
函数之前调用了它。上面代码等效于以下代码:
function add(a, b){
return a + b;
}
let x = 20,
y = 10;
let result = add(x,y);
console.log(result); // 👉 30
Code language: JavaScript (javascript)
在执行上下文的创建阶段,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;
}
Code language: JavaScript (javascript)
如果您执行代码,将会发生以下错误:
Uncaught ReferenceError: add is not defined
Code language: plaintext (plaintext)
在全局执行上下文的创建阶段,JavaScript 引擎会在内存中创建 add
变量,并将它的值初始化为 undefined
。
在执行以下代码时,add
为 undefined
,因此它不是一个函数:
let result = add(x,y);
Code language: JavaScript (javascript)
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;
Code language: JavaScript (javascript)
该代码也会发出与函数表达式示例相同的错误,因为箭头函数是定义函数表达式的语法糖。
Uncaught ReferenceError: add is not defined
Code language: plaintext (plaintext)
与函数表达式类似,箭头函数不会被提升。
总结
- JavaScript 提升发生在执行上下文的创建阶段,将变量和函数声明移至脚本的顶部。
- JavaScript 引擎会提升使用
let
关键字声明的变量,但它不会像使用var
关键字声明的变量那样初始化它们。 - JavaScript 引擎不会提升函数表达式和箭头函数。