1. 什么是变量提升
变量提升就是发生在函数执行前,浏览器会进行一次预编译,在这个阶段浏览器会将所有的 var function 关键字进行变量提升,var在这个阶段是只定义不声明,funnction 是既定义又声明。
(而在这个预定义阶段还会 确定 执行上下文 执行上下文栈,确定this指,确定作用域,作用域链 等其他的)
2.对于变量提升分为以下几种情况
- 带
var和不带var - 等号左边下的变量提升
- 条件判断下的变量提升
- 重名问题下的变量提升
- 函数形参的变量提升
- 非匿名自执行函数的变量提升
2.1带 var 不带var 情况
- 在全局作用域下,带 var 的情况和不带 var 情况 所定义的变量都是在 Windows 上新增了一个属性
- 在私有作用域下,带
var和不带var的情况是有所不同的,带有var的 是在当前作用域进行变量提升,不带var是会先上级作用域查找,如果上级作用域没有找到window 那么就会一直向上查找,直到找到为止。
2.2等号左边的变量提升
- 普通函数左边的变量提升
- 匿名函数下带有
=的变量提升(只提升=左边的部分)
print()
var print = function() {
console.log('林一一')
}
print()
/*输出
Uncaught TypeError: print is not a function
/
思路:同样由于变量提升机制带 var 的 print 是一开始值是 undefined,所以 print() 这时还不是一个函数,所以报出 类型错误TypeError
2.3条件判断下的变量提升
2.4重名问题下的变量提升
带var和function重名的情况下变量提升优先级,函数先执行- 变量重名在变量提升阶段会重新定义也就是赋值
2.5函数形参的变量提升
- 函数的形参也会进行一次变量提升
2.6非匿名自执行函数的变量提升
- 匿名函数在全局作用域下是不具备函数变量名提升的
- 匿名函数自执行函数在自己的作用域内具有正常的变量名提升
- 非匿名自执行函数的函数名在自己的作用域内变量提升,且修改函数名的值无效,这是非匿名函数和普通函数的差别
var a = 10;
(function a(){
console.log(a)
a = 20
console.log(a)
})()
// ƒ a(){a = 20 console.log(a)} ƒ a(){a = 20 console.log(a)}