var a
if (true) {
console.log(a);
a = 5
function a() { }
function b() { }
a = 0
console.log(a);
}
console.log(a);
console.log(b);
ECMAScript并不推荐在if语句中声明函数,但是按照如上写法运行时,控制台并不报错。
逐行分析:
变量提升(var以及function提升),首先将var a 和 function a() { } function b() { }提升。如果处于函数中,就提到函数的顶部;全局中就会提升到全局的顶部。注意
:var 优先级高于 function。
但是由于if语句中({}作用域)定义函数为非标准写法,所以函数a、b提升后并不是函数,此时全局作用域中的a、b是undefined。
if (true)
进入if判断后,函数a、b提升到了块级作用域,即if语句中。
所以第一次打印a为是块级作用域中的数据,即: f a() { }。
a = 5
a = 5改变的是块级作用域中的a,即f a() { } 变为了 5,至此,全局a还是undefined,if语句的块级作用域中a变成了5。
function a () {}
由于if中定义function是非标准写法,所以这一步会造成将块级作用域中的a(上一步操作后,当前为5)赋值给全局中的a。
至此,全局中a为5,if块级作用域中a为5。
function b () {}
同上一步,由于if中定义function是非标准写法,所以这一步会造成将块级作用域中的b(上一步操作后,当前为f b() { })赋值给全局中的b。
至此,全局中b为f b() { },if块级作用域中b为f b() { }。
a = 0
将if块级作用域中的a重新赋值为0。
至此,全局中a为5,if块级作用域中a为0。
console.log(a)
取当前作用域(if)中的a,所以打印0。
console.log(a) console.log(b)
最后两步取得是全局的a和b,所以分别打印5和 f b() { }。
结果
所以实际开发中要符合ECMAScript的规范并且尽可能少的使用var,以免造成bug。