“块级”作用域小例子
首先看一下下面这段代码输出什么:
var a
if (true) {
a = 1
function a() {}
function b() {}
a = 2
console.log(a)
}
console.log(a)
console.log(b)
输出结果:
2
1
[Function: b]
在第二行 if (true) 那里打个端点调试一下:
代码运行完第1行时:
现象:声明了两个变量:
a 和 b ,它们的值都是 undefined
分析:a 变量使用了 var 进行了显式声明; b 变量由 {} 代码块中的函数声明提升到了顶部
代码运行完第2行时:
现象:全局作用域的变量
a 和 b 值并没有变化;新建了一个“块级”作用域,其中包含两个变量 a 和 b,并且值都为函数
分析:{}包裹的代码块将创建“块级”作用域,代码块中的函数声明被提升到了块顶并被初始化为对应的函数
*我们发现到代码块中其实还初始化了一个 this ,它的值是一个空对象 {} *
代码运行完第3行时:
现象:全局作用域的变量
a 和 b 值并没有变化;“块级”作用域的变量 a 被重新赋值为 1
分析:第2行代码对变量a重新赋值,就涉及从作用域链中查找变量a,显然首先从“块级”作用域中找到了变量 a ,则对其进行了赋值操作
代码运行完第4行时:
现象:全局作用域的变量
a 被重新赋值为 1
分析:这一行很诡异,因为它改变了全局作用域变量 a 的值
代码运行完第5行时:
现象:全局作用域的变量
b 被重新赋值为 函数b
分析:这一行可以理解为被提升到全局作用域的变量 b 进行了初始化
代码运行完第6行时:
现象:“块级”作用域的变量
a 被重新赋值为 2
分析:第6行代码对变量a重新赋值,就涉及从作用域链中查找变量a,显然首先从“块级”作用域中找到了变量 a ,则对其进行了赋值操作
第7行打印变量a,是从“块级”作用域中查找到的,打印 '2',执行完此行后块中的代码执行完毕,则“块级”作用域被销毁
第8行打印变量a,是从全局作用域中查找到的,打印 '1'
第9行打印变量b,是从全局作用域中查找到的,打印 '函数b'
例子的几种变化
再看一下下面几个例子:
eg1:
var a;
if (true) {
// a = 1
function a() {}
function b() {}
a = 2;
console.log(a);
}
console.log(a);
console.log(b);
输出:
2
[Function: a]
[Function: b]
eg2:
var a;
console.log(a)
console.log(b)
if (true) {
// a = 1
function a() {}
function b() {}
a = 2;
console.log(a);
}
console.log(a);
console.log(b);
输出:
undefined
undefined
2
[Function: a]
[Function: b]
eg3:
var a;
console.log(a);
console.log(b);
function a() {}
function b() {}
a = 2;
console.log(a);
console.log(b);
输出:
[Function: a]
[Function: b]
2
[Function: b]
总结
- 函数声明将被提升
- 非代码块中的函数声明将被提升到外部作用域顶端,并直接被初始化为函数
- 代码块中的函数声明也将被提升到外部作用域顶端,但不会被初始化
- 代码块中声明的函数会被提升到外部作用域,但是被提升到外部作用域的变量值会受到代码块中变量赋值的影响
不要在代码块中声明函数