- 变量申明晋升和函数申明晋升就是将申明的变量或者函数,晋升至所在作用域的顶部。
平时咱们都认为JavaScript代码是由上向下执行的,然而也有非凡状况,这个状况就会扭转,晋升就属于非凡的状况。
//看以下示例代码: a=2; var a; console.log(a)//2
后果不是报错,而是2。
咱们常见的定义形式是var a = 2
。
其实这是两个申明。var a是定义申明,a=2是赋值申明。定义申明先在编译期进行,赋值申明留在原地期待执行。所以以上代码中,var a是会先被进行的。 输入的后果为2。
//看以下示例代码console.log(a)//undefinedvar a;a=2;
只有a在赋值前被输入的话,就会输入undefined(不是报错)。
这种状况下很多人认为会抛出ReferenceError: a is not defined
下面咱们说过定义申明var a是在编译期进行的,就如var a的地位被挪动到了顶部,这个行为就是晋升
。
所以这段代码的真正执行程序应该是:
var a;console.log(a)//undefineda=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();//TypeErrora();//ReferenceErrorvar test= function a(){ //...}
如上,函数表达式并不会被晋升!
这段代码的真实情况能够这样了解:
var test;test();//TypeErrora();//ReferenceErrorvar test= function a(){ //...}
变量申明和函数申明的优先级
- 函数申明的优先级>变量申明
test()//1var test;function test(){ console.log(1)}test= function a(){ console.log(2)}
这段代码被引擎解析的实在程序:
function test(){ console.log(1)};test();//1var test;test= function a(){ console.log(2)}
只会输入1。
如果遇到函数反复定义:
test();//2function test(){ console.log(1)};function test(){ console.log(2)};
前面申明的函数会笼罩之前的。
如果是在块内申明函数:
test()//TypeError:test is not a functionvar a=true;if(a){ function test(){ console.log(true) }}else{ function test(){ console.log(false) }}
为什么会有这样的状况?因为块也会造成一个作用域,所以要防止如此应用。