你不知道的JavaScript(二)变量提升

来源:互联网 发布:python 复杂网络 编辑:程序博客网 时间:2024/06/06 03:41

变量提升原理

看下面的简单例子:

console.log(a);var a =2;

JavaScript会将上面的声明看成两个声明:var a;a=2;。第一个定义声明在编译阶段进行,第二个赋值声明会被留在原地等待执行阶段。
第一个代码片段会以如下形式进行处理:

var a;console.log(a);a = 2;

这个过程就好像变量声明(函数声明也一样)从他们在代码中出现的位置被“移动”到了最上面,这个过程就叫作提升。

函数优先

函数声明和变量声明都会被提升,但是有一个值得注意的细节:函数首先会被提升,然后才是变量。
考虑下面的代码:

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

结果会输出1,而不是2。这个代码片段会被引擎理解为如下形式:

function foo() {    console.log(1);}foo();//1foo=function() {    console.log(2);}

尽管var foo 出现在function foo()的声明之前,但它是重复的声明,因此被忽略,因为函数的声明会被提升到普通变量之前。
虽然重复的var声明会被忽略掉,但是出现在后面的函数声明能够覆盖之前的声明:

foo();//3function foo() {    console.log(1);}var foo=function() {    console.log(2);}function foo() {    console.log(3);}

以上这些内容虽然听起来没有太大用处,但是它说明了在同一个作用域中进行重复定义非常糟糕的,而且经常会导致各种奇怪的问题。
一个普通快内部的函数声明通常会被提升到所在作用域的顶部,这个过程并不会像下面的代码暗示的那样可以被条件判断所控制:

foo();var a=true;if(a) {    function foo() { console.log('a'); }}else {    function foo() { console.log('b') }}

上述代码会被理解为如下形式:

function foo() {console.log('b')};var a;foo();a=true;if(a) {}else{}

所以这个行为并不可靠,应该尽可能避免在块内部声明函数。

原创粉丝点击