在“当前上下文”中,代码执行之前、浏览器首先会把所有带var/function关键字的进行提前声明或者定义:
带var的只是提前声明
带function的,声明+定义(赋值)都完成了
总结几点:
- let/const/import/class声明的变量不存在变量提升
- 重复声明的问题
- 推荐使用函数表达式、确保函数执行只能放在“创建函数”的下面,保证逻辑严谨性
- 条件判断:在当前上下文中,变量提升阶段,不论条件是否成立都要进行变量提升
--var:还是只声明
--function:判断体中的函数,在变量提升阶段,只声明不赋值
举例说明:
1、
console.log(a) // undefined 变量提升 var a;然后才是代码执行,a只声明没定义,所以是undefined
var a = 12
console.log(b) // Uncaught ReferenceError: Cannot access 'b' before initialization
let b = 12 // 上一句报错,这里不执行了
2、
console.log(fn)
function fn() {
console.log(1)
}
console.log(fn)
var fn = 12
console.log(fn)
function fn() {
console.log(2)
}
console.log(fn)
![](https://img.haomeiwen.com/i10486578/6b913266a69da382.png)
1、函数自上而下执行
2、遇到带var和function的要变量提升(且基于var和function声明的而变量存在GO中,)
3、var 只声明,function声明+定义
4、变量提升开始:
function fn(){console.log(1)}
此时GO中存储的是:
function fn : 0x001(函数的堆内存)
5、var fn = 12
6、此时GO中存的是:
function fn : 0x001(函数的堆内存)
var fn
但是fn已经声明过了,GO是一个对象,不允许重复声明变量,所以GO中还是只有一个fn
function fn : 0x001(函数的堆内存)
7、再次遇到function fn(){console.log(2)}
同理fn已经声明过了,不再重复声明,但是函数却不同,所以重新创建一个堆内存:0x002
8、到此变量提升易操作完毕,GO中存储的是:
fn : 0x002
9、变量提升结束,代码开始执行
第一个console.log(fn) :fn指向的地址是0x002 也就是 函数 fn(){console,log(2)}
10、第二个console.log(fn) 同上:fn指向的地址是0x002 也就是 函数 fn(){console,log(2)}
11、var fn = 12 被重新赋值为12
12、所以后边两个console的值都是12
![](https://img.haomeiwen.com/i10486578/6ccab0078eccf3b3.png)
3、
fn() // 1
function fn() {
console.log(1)
}
fn() // 1
因为变量提升机制,导致可以在创建函数的代码之前使用函数,这样逻辑就比较松散,真是项目中推荐使用“函数表达式”,把一个函数作为值,赋值给一个变量
比如:
const fn = function (){
console.log(1)
}
4、
console.log(a) // undefined
if(!('a' in window)) {
var a = 12
}
console.log(a) // undefined
不论判断条件是否成立,都要变量提升
- var的还是只声明
- 带function的,在变量提升阶段,也是只声明;不在怕判断体中的funcion是声明+定义
代码执行:v变脸提升:var a -->window.a
'a' in window:检测‘a’是否是window的属性
‘a’是widow的属性,再取反是false
所以判断不成立
a没有赋值
最后输出a还是undefined
注意:'a'字符串a in window 是检测这个属性名是否在window中的属性‘
;
a in window 是检测a的值是否是window的属性,a没复制,它的值是undefined,undefined肯定不是window的属性
网友评论