ES5中是不存在块级作用域的。
ES6中开始出现。
1. 块级作用域与普通变量
例子:
function f() {
let n = 5
if (true) {
let n = 10
}
console.log(n) // 5
}
以上代码中有两个代码块 可见输出的是外部的n 值为 5,这表示外层代码块不受内层代码块的影响
这其实也是 let
在发挥作用,假使if
代码块内部使用的不是let
而是var
,那么输出的值就会是 10
这意味着:内层作用域可以定义外层作用域的同名变量,并且两个作用域中的同名变量互不影响
2. 块级作用域与函数声明
我们先复习两个概念:
- 函数声明
function f() {
console.log("123") }
- 函数表达式
var f = function () {
console.log("123") }
ES5规定函数只能在顶层作用域和函数作用域之内。
ES6明确允许在块级作用域内声明函数。
例子:
function f() {
console.log("out") }
(function () {
if (false) {
function f() {
console.log("inside") }
}
f() // undefined
} ())
这段代码当时疑惑了我很久,于是我去问学姐们。
学姐解释了一会儿,再加上我百度,得出了以下结论:
在立即执行函数中,我们在 一个条件一定为 false
的 if
语句代码块内部 对一个在外部已经进行过声明的函数进行声明
会发生什么呢,function f() { console.log("inside") }
语句会将if
语句击穿,也就是说,进行变量提升,
这里 if
后括号内的 false
和 true
的区别就是:
如果是true
,会对f
进行重新声明,最终打印“inside”;
如果是false
,那么该语句会自动进行 函数声明到函数表达式的转换,
即:function f() { console.log("inside") }
-> var f = function () { console.log("inside") }
,
但是提升 只会提升var f
这部分,对函数进行赋值的部分不会得到提升,这就是例子中结果为undefined
的原因(var f
这句代码没有给f
初始值,所以值为undefined
)。
如果if
的代码块不写在函数(普通函数大概也是,我试过一两个情况)内,就不会发生这种迷惑的情况。(大概)
3. 关于变量提升
简单几句话概括一下,
如果在一个代码块中 我们在一个 变量 被 声明并赋值 之前 就使用了它,前提是之后进行了声明和赋值,那么,如果输出这个变量的话,不会报错,会输出undefined
,这就是变量提升
console.log(a) // undefined
var a = "我喜欢的是二次元美少女,谢谢!"
实际上 ES6 会操作一波,让代码变成这样:
var a
console.log(a)
a = "我喜欢的是二次元美少女,谢谢!"
暂时这样子吧。