- 变量声明提升和函数声明提升就是将声明的变量或者函数,提升至所在作用域的顶部。
平时我们都认为JavaScript代码是由上向下执行的,但是也有特殊情况,这个情况就会改变,提升就属于特殊的情况。
//看以下示例代码:
a=2;
var a;
console.log(a)//2
结果不是报错,而是2。
我们常见的定义方式是var a = 2
。
其实这是两个声明。var a是定义声明,a=2是赋值声明。定义声明先在编译期进行,赋值声明留在原地等待执行。所以以上代码中,var a是会先被进行的。 输出的结果为2。
//看以下示例代码
console.log(a)//undefined
var a;
a=2;
只要a在赋值前被输出的话,就会输出undefined(不是报错)。
这种情况下很多人认为会抛出ReferenceError: a is not defined
上面我们说过定义声明var a是在编译期进行的,就如var a的位置被移动到了顶部,这个行为就是提升
。
所以这段代码的真正执行顺序应该是:
var a;
console.log(a)//undefined
a=2;
只有声明本身会被提升,其他的运行逻辑不变。
要注意的是变量的提升只提升至所在作用域的顶部。
在函数中同理,函数拥有自己的作用域,所以函数中的变量提升,也是提升到这个作用域的顶部,例如:
test();
function test(){
console.log(a)//undefine
var a =2
}
真实的执行顺序是:
function test(){
var a;
console.log(a)//undefine
a =2
}
test();
如果是所在作用域的外部输出变量,结果仍然是报错(ReferenceError: a is not defined)
函数声明也被提升了并且调用,所以函数内的代码也执行,并不会报错。
我们再看一下函数表达式:
test();//TypeError
a();//ReferenceError
var test= function a(){
//...
}
如上,函数表达式并不会被提升!
这段代码的真实情况可以这样理解:
var test;
test();//TypeError
a();//ReferenceError
var test= function a(){
//...
}
变量声明和函数声明的优先级
- 函数声明的优先级>变量声明
test()//1
var test;
function test(){
console.log(1)
}
test= function a(){
console.log(2)
}
这段代码被引擎解析的真实顺序:
function test(){
console.log(1)
};
test();//1
var test;
test= function a(){
console.log(2)
}
只会输出1。
如果遇到函数重复定义:
test();//2
function test(){
console.log(1)
};
function test(){
console.log(2)
};
后面声明的函数会覆盖之前的。
如果是在块内声明函数:
test()//TypeError:test is not a function
var a=true;
if(a){
function test(){
console.log(true)
}
}else{
function test(){
console.log(false)
}
}
为什么会有这样的情况?因为块也会形成一个作用域,所以要避免如此使用。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。