声明提升

我们知道,JavaScript语句在编译阶段会将所有函数和变量的声明进行提升,例如:

console.log(a);  // undefined

var a=100;

输出是undefined,因为这个代码片段会被解析成:

var a;

console.log(a); // undefined

a=2;

变量a的声明会被提升到所在作用域(即全局作用域)的顶部,函数也不例外(注意,函数表达式是不会被提升的,只有函数声明才会被提升):

foo();     // 2

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

这个代码片段会被解析成:

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

foo();    // 2

那函数和变量哪个会被优先提升呢?来看一个例子:

foo();    // 2

var foo;

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

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

输出是2,实际上代码会被解析成:

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

foo();  // 2

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

虽然foo函数的声明在var foo;之后,但由于函数被优先提升了,所以var foo;也就因为重复声明而被忽略。

注意,出现在后面的函数声明可能会覆盖前面的:

foo();  // 3

functio foo(){
    console.log(1);
}

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


function foo(){
    console.log(3);
}

foo();执行结果是3。实际上代码会被解析成:

functio foo(){
    console.log(1);
}

function foo(){
    console.log(3);
}

foo();     // 3

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

声明会被提升到所在作用域的顶部,ES5不会像下面这样被条件语句所控制:

foo();   // 2

if(true){
    function foo(){
        console.log(1);
    }
} else{
    function foo(){
         console.log(2);
    }
}

输出是2而不是1,实际上代码会被解析成:

function foo(){
     console.log(1);
}

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

foo();    // 2

if(true){} else{}

第一个foo函数声明被第二个foo函数声明所覆盖,所以最终执行结果为2,因为尽管foo函数是在if-else语句块里被声明,但ES5没有块作用域(只有函数作用域),所以foo函数声明依然会被提升到全局作用域,就出现了刚才的情况。

posted @ 2018-01-15 15:44  linweiws  阅读(117)  评论(0编辑  收藏  举报