JS难点之hoist

这篇博文是以前在CSDN写的,如今移至sf。编程

有过C或者Java类编程经验的同窗,对于“先声明后使用”的规则很熟悉,若是使用未声明的变量或者函数,编译时程序会报错!可是,JavaScript倒是一个‘大奇葩’,能够在变量或者函数声明以前使用,如今根据个人理解在作一下说明。微信

首先说明JS的hoist分为变量hoist函数hoist两种。函数

1、变量hoist

看一段程序code

       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解析器的解析缘由,它会将当前做用域中声明的全部变量和函数,放在做用域的最开始处。可是变量只有其声明被提早在做用域的最开始处,赋值结果仍然还在原来位置。上述代码对于解析器来讲,实际上是:ip

       var a=10;  
       function fun(){
          var a;  
          console.log(a);  
          a=100;  
          console.log(a);  
       }  

       fun();//undefined   100  
       console.log(a);//10

2、函数hoist

 
讲完变量hoist,如今再讲一下函数hoist,函数hoist又分为两种状况。一种是函数声明,另外一种是函数做为值赋值给变量作用域

先说第一种状况:io

   fun();//2  

   function fun(){console.log(2);} 

在这种状况下,能够看出,函数JS解释器容许在函数声明以前使用函数,其实也就说明,在这种状况,不只函数名提早了,同时,函数体也被提早。因此能够上述代码能够执行。再说第二种状况:console

     fun();  
     var fun=function(){  
        console.log(2);  
     }

结果为:Uncaught TypeError: fun is not a function  能够看出在此例中,函数只是变量声明声明提早,可是赋值没有提早,而且被提早的变量默认为undefined,因此报的错误类型为“typeerror”,由于undefined不是函数,不能被调用。编译

3、变量名和函数名相同时的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。 

相关文章
相关标签/搜索