JS难点之hoist

60次阅读

共计 1879 个字符,预计需要花费 5 分钟才能阅读完成。

这篇博文是之前在 CSDN 写的,现在移至 sf。
有过 C 或者 Java 类编程经验的同学,对于“先声明后使用”的规则很熟悉,如果使用未声明的变量或者函数,编译时程序会报错!但是,JavaScript 却是一个‘大奇葩’,可以在变量或者函数声明之前使用,现在根据我的理解在做一下说明。
首先说明 JS 的 hoist 分为变量 hoist 和函数 hoist 两种。
一、变量 hoist
看一段程序
       var a=10;  
       function fun(){  
         console.log(a);  
         var a=100;  
         console.log(a);  
      }  
       fun();//undefined   100  
       console.log(a);//10  
 
我们知道在 js 中,作用域分为全局作用域和函数作用域两种(ES6 新特性,增加了块级作用域,另做说明)。全局变量声明有三种方式:

var(关键字)+ 变量名(标识符)方式在 function 外部声明,显示声明
没有使用 var,直接给标识符赋值,隐式声明
使用 window 全局对象来声明,全局对象的属性也应是全局变量 eg:window.test=50; alert(test);

  
好,很显然,var a=10; 在程序中是全局变量。那么,按照我们正常的逻辑输出结果为:10  100  10。但是,实际输出结果为:undefined 100  10, 其实是 JS 解析器的解析原因,它会将当前作用域中声明的所有变量和函数,放在作用域的最开始处。但是变量只有其声明被提前在作用域的最开始处,赋值结果仍然还在原来位置。上述代码对于解析器来说,其实是:
       var a=10;  
       function fun(){
          var a;  
          console.log(a);  
          a=100;  
          console.log(a);  
       }  

       fun();//undefined   100  
       console.log(a);//10
二、函数 hoist
 讲完变量 hoist,现在再讲一下函数 hoist,函数 hoist 又分为两种情况。一种是函数声明,另一种是函数作为值赋值给变量。
先说第一种情况:
   fun();//2  

   function fun(){console.log(2);} 
在这种情况下,可以看出,函数 JS 解释器允许在函数声明之前使用函数,其实也就说明,在这种情况,不仅函数名提前了,同时,函数体也被提前。所以可以上述代码可以执行。再说第二种情况:
     fun();  
     var fun=function(){  
        console.log(2);  
     }
结果为:Uncaught TypeError: fun is not a function  可以看出在此例中,函数只是变量声明声明提前,但是赋值没有提前,并且被提前的变量默认为 undefined,所以报的错误类型为“typeerror”,因为 undefined 不是函数,不能被调用。
三、变量名和函数名相同时的 hoist
       function fun(){console.log(1);}  
       fun();//2  
       function fun(){console.log(2);}  
       fun();//2  
       var fun=100;  
       console.log(fun);//100  
       fun();// 报错
在此例中,函数名和变量名相同,都是 fun,都会提前,那么在提前时,有什么需要注意的地方呢?

函数声明比变量声明更置顶
声明过得变量不会重复声明

  
所以上述代码等效于:
function fun(){console.log(1);}  
     function fun(){console.log(2);}// 函数体覆盖上一层函数体  
     var fun;// 实际无效  
     fun();  
     fun();  
     fun=100;  
     console.log(fun);  
     fun();
以上就是本人对于 JS 的 hoist 问题的理解,如果哪位同学,发现其中有误,欢迎指正!我的微信号为:Alfred-kai。

正文完
 0