function声明在块级作用域需注意的点
练习题1:
var a = 111 if(1){ console.log(a,window.a) a = 222 console.log(a,window.a) function a(){} console.log(a,window.a) }
练习题2:
function a() { console.log('111'); } (function () { if (false) { function a() { console.log('222'); } } a(); }());
以 function a(){} 这种方式来声明函数有几个需要注意的地方
1.在只支持es5的运行环境下(如ie10及以下),声明提前是提前到当前局部或全局作用域的最前面(优先于var声明的变量)
a() // 2 var a = 1; function a(){ console.log(2) } console.log(a); // 1 上述代码声明提前后,等同于以下代码 function a(){ console.log(2) } a = 1; a() // 2 console.log(a); // 1
(function (){ if(false){ function a(){} console.log(a) // function } console.log(a) // function })() console.log(a) // 报错:未定义 在只支持es5的运行环境下,上述代码声明提前后,等同于以下代码 (function (){ function a(){} if(false){ console.log(a) // function } console.log(a) // function })() console.log(a) // 报错:未定义
2.在支持块级作用域(es6)的运行环境下,变量声明先提前到当前块级作用域的最前面,并判断在当前局部或全局作用域中是否存在该变量,若不存在,则立即声明该变量,值为undefined。在执行到该声明语句位置时,会存在变量突破,即:将该变量及其在当前块级作用域中的值拷贝到其局部作用域(没有局部作用域时就是全局作用域)中。
{ console.log(a,window.a) a = 222 console.log(a,window.a) function a(){} // 先声明提前到块级作用域顶部,执行到这个地方时,会存在变量突破,即:将块级作用域中当前a的值赋值给window.a } //在支持es6的运行环境下,上述代码声明提前后,等同于以下代码 window.a; { function a(){} console.log(a,window.a) a = 222 console.log(a,window.a) window.a = a }
注意:ie11支持es6代码,但是在ie11中变量提升的时候就会进行变量突破
3.在只支持es5的运行环境下(如ie10及以下),不存在块级作用域,只会存在变量提升
不自见,故明;不自是,故彰;不自伐,故有功;不自矜,故长。