首先要记住:函数声明置顶比变量声明置顶更优先
因为在预解析阶段变量只声明了,但未赋值,而函数不一样,它在预解析阶段就已经声明和赋值了,它的值就是函数这个对象
然后来看代码:
1、var a = 0
:声明了一个变量a
,并赋值为0
2、看if里面代码;我们先就看a=1
和function a(){}
// 因为存在变量提升,代码可以分析为这样,先不看console
function a(){}
a = 1
开始执行if代码块,if代码块内有一个函数名为a的函数声明,
且函数a下面有一个变量名为a的变量,且赋值为1,这里便开始了难点分析。
首先看函数a,由于在执行if代码块的时候,并没有调用函数a,因此函数a并没有起作用;
但是执行到a=1的时候,js是这样做的:
1.首先查找变量a的地址,从系统内存中开始按照作用域链查找;
2.由于作用域链的查找顺序是由里向外的,故要先从if代码块里面开始查找;
3.在查找的过程中,发现if代码块中已经声明了一个函数名为a的函数(重名问题!),
所以查找到函数名为a的函数后,这里便不再往外查找;
所以这里的a=1其实是将1赋值给了函数名为a的这个函数对象!
3、第一个console
;window.a
找的是全局的变量a
,在全局下已经声明有了a
,所以值为0
,后面的a
会现在if代码块
里查找,变量提升了,所以打印的是function a(){}
4、执行到a=1
;因为没有var
关键字,所以a
相当于一个全局变量,此时a
就会覆盖原来a
的值,变为1
;而if代码块里也直接找寻到名为a
的函数,所以将a
赋值为1,因此第二个console值为 0, 1
5、第三个console
,此时已经赋过一次值,在打印,就是1, 1
6、第四个console
,a=21
,在if代码块里查找,找到了函数名a
,将值赋给了这个函数对象;所以这次打印的是1,21
7、第五个console
,就是打印全局的a,所以是1, 1
以上就是我的理解,如果有错,欢迎指出,共同理解进步哈?
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…