JS声明提升
# 产生因素
函数在执行时会先创建当前的执行上下文环境。其中产生声明提升的因素有以下两点:
- 变量定义
- 函数声明
# 编译阶段
当 js 引擎开始解析脚本时,这时代码还没有运行,会先给代码中的变量、函数声明设置内存,并暂时将变量赋值为 undefined,函数先声明为可使用;为后面即将执行的代码做准备,这个阶段就是编译阶段。
比如 var a = 1; JS 引擎会将其看作两个声明:var a; 和 a = 1;。第一个定义声明在编译阶段进行,第二个赋值声明会被留在原地等待执行阶段。
# 变量声明提升
只有 var 声明的变量存在变量提升;let、const 会形成块级作用域,造成暂时性死区。
console.log(a); // undefined
var a = 1;
console.log(fun); // undefined
var fun = function () {};
1
2
3
4
5
2
3
4
5
上面例子都会会打印出 'undefined',变量声明提升会将变量声明提升到作用域顶部,但只会提升声明部分,不会提升赋值部分,实际提升后结果如下:
var a;
console.log(a);
a = 1;
var fun;
console.log(fun);
fun = function () {};
1
2
3
4
5
6
7
2
3
4
5
6
7
# 函数声明提升
func();
function func() {}
1
2
2
上例不会报错,因为 ‘函数声明提升’,即将函数声明提升(整体)到作用域顶部(注意是函数声明,不包括函数表达式),实际提升后结果同下:
function func() {}
func();
1
2
2
# 函数声明和变量声明提升的优先顺序
var func = 1
console.log(typeof(func)) // number
function func () {}
-----
console.log(typeof(func)) // function
function func () {}
var func = 1
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
上两例将分别输出 ‘number’、'function',原因是 函数声明提升优先于变量提升,函数声明会被变量赋值影响,但不会被变量声明影响,实际提升后结果如下:
function func () {}
var func = 10
console.log(typeof(func))
-----
function func () {}
var func
console.log(typeof(func))
func = 10
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 局部与全局变量
a = 1;
function func() {
window.a = 2;
console.log(a); // undefined
var a;
console.log(window.a); // 2
}
func();
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
上例将会分别打印出 'undefined'、'5',第一处为局部变量,第二处为全局变量,实际提升后结果如下:
function func() {
var a;
window.a = 2;
console.log(a); // undefined
console.log(window.a); // 2
}
var a;
a = 1;
func();
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
上次更新: 2022/09/06, 10:30:04