提升
之前我们讲过var a = 2;后发生了什么,它回进行两个部分,第一部分是编译,而第二部分是执行。故应该是声明在前,赋值在后
a =2;
var a;
console.log(a);//2
上面三行代码被这样执行:
var a ;
a = 2;
console.log(a);
but ...
console.log(a);//undefined
var a = 2;
上面两行怠慢会被这样执行:
var a ;
console.log(a);
a = 2;
这就是变量提升
只有声明本身会被提升,而赋值或其他运行逻辑会留在原地,接下来看下函数的提升
foo();
function foo(){
console.log(a);//undefined
var a =2 ;
}
foo可以被正常执行,因为它函数的声明被提升了,而且函数内部的变量提升不会超出函数范围,相当于如下代码:
function foo(){
var a;
console.log(a);//undefined
a = 2;
}
foo();
but...
需要谨记的一点是函数声明可以被提升,但是函数表达式却不会被提升。
foo();//TypeError
var foo = function bar(){
//
};
执行foo()在前,赋值在后,foo()由于对undefined值进行函数调用而导致非法错误,即使是具名的函数表达式,名称标识符在赋值之前也无法在所在作用域中使用:
foo();//TypeError
bar();//ReferenceError
var foo = function bar(){
}
实际上它是这样执行的:
var foo;
foo();
bar();
foo = function(){
var bar = ...self...
}
函数优先
函数会首先被提升,然后才是变量。
foo();//1
var foo;
function foo(){
console.log(1);
}
foo = function(){
console.log(2);
}
实际上,是这样的:
function foo(){
console.log(1);
}
foo();
foo = function(){
console.log(a);
}
再看:尽量避免在块内些函数声明。
foo();//'b'
var a = true;
if(a){
function foo(){
console.log('a');
}
}else{
function foo(){
console.log('b');
}
}