JavaScript Hoisting跟“先有鸡还是先有蛋”
代码很简单,但是有个很有趣的东西。
我们都知道:JavaScript代码是由上而下,逐行解释执行的。
那么先看这段代码:
a = 2; var a; console.log( a );
控制台上会输出什么?
或许你会觉得是输出个undefined
,因为a定义声明是在a=2这个赋值声明之后的,console.log(a)的时候,a是没有赋值的,所以是undefined
。然而事实并非如此。输出是:2。
再看这段代码:
console.log( a ); var a = 2;
通过上面的例子:或许你觉着是输出2,或者抛ReferenceError
错。但这两个想法都是错的。输出是undefined
。
这两段代码阐述了一个问题:先有鸡还是先有蛋。
用JavaScript语言来提问就是:先有声明(declaration ),还是先有赋值(assignment)?
-------------------------------------------------------------------------------------------------------------------------------------
对于JavaScript来说是,先有声明。
如何来理解“先有声明”呢?
JavaScript代码在执行之前,会编译一下(compile first),编译的其中一部分就是,变量和函数的声明。
对于上面两个例子可以这样来解释:
第一段代码根据执行顺序,可以这样来理解:
第一步:
var a;
第二步:
a = 2; console.log(a);
对于第二段代码,可以这样来理解:
第一步:
var a;
第二步:
console.log(a)//所以才undefined a =2 ;
上面的这个过程就是JavaScript声明提升(Hoisting)。提升嘛,就是从底层位置到高层位置。
-------------------------------------------------------------------------------------------------------------------------------------
Hoisting的几个要点:
- 提升的是声明,赋值、可执行的代码段是不提升的。
-
提升是按照作用域来提升的,即声明只能提升到所在作用域的最上面。例子:
foo(); function foo() { console.log( a ); // undefined var a = 2; }
这段代码的执行过程其实是这样的:function foo() { var a; console.log( a ); // undefined a = 2; } foo();
-
函数声明(Function delaration)能提升,但是函数表达式(Function expression)不能提升,例:
foo(); // not ReferenceError, but TypeError! var foo = function bar() { // ... };
参考:
JavaScript Hoisting
-------------------------------------------------------------------------------------------------------------------------------------