直觉上会认为 JavaScript 代码在执行时是由上到下一行一行执行的。但实际上这并不完全正确,有一种特殊情况会导致这个假设是错误的。
a = 2
var a;
console.log(a); //2
和
console.log(a);//undefined
var a=2;
编译器来分析上述代码
编译器会把代码分为
var a 在编译阶段进行。
a = 2 赋值声明会被留在原地等待执行阶段。
第一部分是编译,而第二部分是执行。
只有声明本身会被提升,而赋值或其他运行逻辑会留在原地。如果提升改变了代码执行的顺序,会造成非常严重的破坏。
这就可以解释
a = 2
var a;
console.log(a); //2
转化代为为
var a 声明被提升
a = 2
console.log(a); //2
函数声明 和 函数表达式
foo() 函数声明
var foo=function foo() {} 函数表达式
function foo(){
}
foo() //不报错会 函数声明被提升了
和
foo() //报错
var foo=function bar(){ //函数表达式却不会被提升。
}
什么原因呢?
foo() 不会被赋值
var foo=function bar(){} 被赋值了
很容易理解了
var foo;
foo() //没有值所以会报错了!
foo=function bar(){}
函数优先
函数声明和变量声明都会被提升。但是一个值得注意的细节(这个细节可以出现在有多个“重复”声明的代码中)是函数会首先被提升,然后才是变量。
foo(); // 1
var foo;
function foo() {
console.log( 1 );
}
foo = function() {
console.log( 2 );
};
编译器代码顺序
function foo() {
console.log(1)
}
foo()
var foo; 被忽略
foo = function() {
console.log( 2 );
};
注意,var foo 尽管出现在 function foo()... 的声明之前,但它是重复的声明(因此被忽略了),因为函数声明会被提升到普通变量之前。
尽管重复的 var 声明会被忽略掉,但出现在后面的函数声明还是可以覆盖前面的。
例如如下
foo(); // 3
function foo() {
console.log( 1 );
}
var foo = function() {
console.log( 2 );
};
function foo() {
console.log( 3 );
}