在JavaScript中,变量和函数在声明之前就可以使用,这个特性被称为 “声明提前”,“声明提前” 这步操作是在“预编译”的时候进行的,也就是在代码开始运行之前,变量声明和函数声明都会被提升到顶部,这两种提升还有些略微的不同。
变量提升:会将变量的声明提升,但并不会把变量的赋值也提升。
函数提升:函数的提升会将整个函数都提到前面去。
变量提升
b = 2;
var b;
alert(b);
//2 并不会报错
这段代码等价于:
var b; //变量声明被提前
b = 2;
alert(b);
//2
但是被提前的是声明,赋值语句并不会提前。看下面这个例子:
alert(b);
var b = 2;
alert(b);
//undefined
//2
等价于
var b;
alert(b);
b = 2;
alert(b);
//undefined
//2
要注意的是,这里的第一个结果是 undefined 而不是 b is not defined 。
第一个结果并非是在作用域中找不到 b ,b 已经被声明定义,只是没有进行初始化,所以是
b 的值为 undefined 。
函数提升
fun();
function fun() {
alert("123");
}
//123
可以看出,函数定义也被提升了,而且整个函数体都被提到了前面。
等价于:
function fun() {
alert("123");
}
fun();
//123
函数有两种定义方法,一种是函数声明,一种是函数表达式。看看下面的例子的结果。
fun();
var fun = function () {
alert("123");
};
//fun is not a function
原因在于函数表达式并非是一个函数声明,而是位于一个初始化语句中,它等价于下面这个例子。
在执行到函数所在的语句之前,变量 fun 并不会保存对函数的引用,也就是说在这里 fun 并不是一个函数,而是一个变量。这是一个变量提升而不是函数提升,被提升的变量 fun 并不会进行赋值,而是要在执行到赋值语句时,才会将函数体赋给 fun。
var fun;
fun();
fun = function () {
alert("123");
};
//fun is not a function
函数声明的优先级高于变量声明
声明提前也是有优先级的,使用同一个标识符的变量和函数,函数被声明的优先级高于变量。
alert(fun);
function fun() {
alert("123");
};
var fun = 456;
/* 结果是:
* fun() {
* alert("123");
* }
*/
看看下面这个例子:
function fun() {
alert("123");
};
var fun = 456;
alert(fun);
//456
因为执行到赋值语句是,fun = 456; fun 被附上了新值。