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及以下),不存在块级作用域,只会存在变量提升

posted @ 2021-02-26 15:57  鳯訡  阅读(235)  评论(0编辑  收藏  举报