这篇博文是以前在CSDN写的,如今移至sf。编程
有过C或者Java类编程经验的同窗,对于“先声明后使用”的规则很熟悉,若是使用未声明的变量或者函数,编译时程序会报错!可是,JavaScript倒是一个‘大奇葩’,能够在变量或者函数声明以前使用,如今根据个人理解在作一下说明。微信
首先说明JS的hoist分为变量hoist
和函数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 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
讲完变量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不是函数,不能被调用。编译
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。