变量提升是啥
JavaScript中存在一种叫做变量提升的东西,那么这种东西是什么呢?不多说,我们先来看一段代码
console.log(a);
var a = 2;
大家可以调出F12去跑一下,发现输出了undefined,这是为啥嘞,明明我们是先调用后声明呀。但是这个其实是因为Js中存在变量提升现象,所以在运行这段代码的时候,他的处理方式是这个样子的:
var a;
console.log(a);
a = 2;
剖析下底层发现编译器会先找到所有声明的变量,并将他与当前的作用域关联起来,然后Js引擎会在后期再给他赋值。所以你可以认为会存在一个类似于预注册的情况,先将变量“预注册”却没有赋值。
顺带一提:变量提升是将变量“预注册”到当前作用域的顶部
console.log(a); //报错,ReferenceError
function test(){
console.log(a);
var a = 2;
}
顺带二提:es6使用let和const声明变量不会出现变量提升
console.log(b);//报错,ReferenceError
const b = 2;
console.log(c);//报错,ReferenceError
const c = 2;
函数提升是啥
说完了声明变量,我们还要来说说声明函数的情况,这个还是存在一定的区别的,但是我们首先来了解一下声明函数的方式。
函数声明和函数表达式
函数声明和函数表达式是两种不同的声明函数的方式,我们继续看代码
//函数声明
function test(){
...//doSth
}
//函数表达式
var test = function(){
...//doSth
}
可以看到,函数表达式就是一条式子,函数声明则简单粗暴直接命名函数。
函数声明和函数表达式的区别
简单的一句概括就是,函数声明会提升而函数表达表达式不会提升,直接上代码
console.log(test1()) // 'this is test1'
function test1(){
return 'this is test1';
}
console.log(test2) // undefined
var test2 = function(){
return 'this is test2'
}
我们可以看到函数声明的函数存在了函数提升,这是因为函数声明的时候函数体也提升了,而函数表达式只是将test2这个变量名提升,如果我们直接运行,他并不会报出ReferenceError而是出现了TypeError。
变量提升和函数提升的比较
有趣的是,虽然变量和函数在声明时都存在提升,但是其实运行过程中我们发现,函数提升会优先于变量提升,继续看代码:
foo();//1
var foo = 2;
function foo(){
console.log(1);
}
以上代码在运行是其实是这样的
function foo(){
console.log(1);
}
foo();//1
}
而var foo = 2会因为重复声明而被忽略掉,因此结果输出1。
顺带一提:后面的函数声明会覆盖前面的函数声明
foo();//2
function foo(){
console.log(1);
}
function foo(){
console.log(2);
}
到此,浅谈结束,不知道有没有漏谈或者模糊出错的知识点,欢迎各位在评论中补充。谢谢阅读。