前言:
在ES6之前,JavaScript没有块级作用域(一对花括号{}即为一个块级作用域),只有全局作用域和函数作用域。变量提升即将变量声明提升到它所在作用域的最开始的部分。
变量提升
- var 会将变量提升到当前作用域最顶端,只提升声明,不提升赋值
- 函数具有作用域,访问变量会优先在当前作用域内寻找
//变量提升
console.log(a); //undefined 存在但未定义
var a=10
console.log(a); //10
//实际运行
var a;
console.log(a); //undefined
a=10;
console.log(a) //10
//函数作用域内
var a=10
function fn(){
console.log(a); //undefined
var a=200;
console.log(a) //200
}
fn()
函数提升
函数书写方式有多种,只有函数声明则会遵循变量提升规则,字面量形式会将函数整体提升
//字面量形式
console.log(a); //function a(){console.log(1)} 函数整体被提升
function a(){
console.log(1);
}
//函数声明
console.log(a); //undefined 相当于变量提升只提升了声明
var a=function a(){
console.log(2);
}
函数提升要比变量提升的优先级要高一些,且不会被变量声明覆盖,但是会被变量赋值之后覆盖。
//优先级
console.log(a); //function
var a=100
function a(){
console.log(2);
}
console.log(a); //100
//实际运行
var a=function(){console.log(2)}
var a;
console.log(a); //function 函数提升不会被变量声明覆盖
a=100;
console.log(a); //100
有个值得注意的细节,函数提升比变量提升优先级高,且不会被变量声明覆盖(第一个a);但是会被变量赋值之后覆盖(第二个a)
会了么,给你出个题试试?
console.log(a);
console.log(a());
var a = 3;
function a() {
console.log(10)
}
console.log(a)
a = 6;
console.log(a());
来看看答案是不是跟你预期的一样
console.log(a); // f a() {console.log(10)}
console.log(a()); // undefined
var a = 3;
function a() {
console.log(10) //10
}
console.log(a) //3
a = 6;
console.log(a()); //a is not a function;
是不是愣了,来看下实际解析的代码
var a=function(){console.log(10)}
var a;
console.log(a) //函数提升不会被变量声明覆盖,所以它依旧是函数
console.log(a()) //小坑,a是函数,返回的是console.log(10),会执行函数打印出10,自身打印一个undefined
a=3
console.log(a) //重新赋值 a变成3
a=6
console.log(a()) //a现在是6,不再是一个函数了,所以报错
是不是很有趣呢!掌握了这个题,本文的知识你就完美吸收了!
我们没有理由说辛苦。
为自己喜欢的事情坚持
为坚持的事情努力
看到自己的进步
其实是件很幸福的事。
也正因为这些辛苦
才让人察觉白驹过隙
才知道自己没有浪费光阴。