JS预解析与作用域链
在函数中,var声明的是局部变量,不带var的是隐式全局变量。
在函数外,var声明的是全局变量,不带var的是隐式全局变量
上代码:
1 | var a = 1; |
分析要点:
函数与变量名重复,变量是局部还是全局。
需要知道js是有预解析的,在预解析的过程中,函数与变量的声明会提前,赋值位置不变,同时注意函数中变量声明的提前只会提升到当前作用域的顶层。
误区:认为程序顺序执行,a被改为10,然后函数返回,a函数不执行。
实际上,函数会预解析,a函数的声明会被提前到a=10之前。
1 | function b(){ |
这时再看代码,注意,代码自上而下,作用域链由内向外。
先是声明了函数b,再声明了a变量,系统会给a一块内存(此时为赋值),
再a=1,变量a被赋值为1;然后执行b函数,函数里面又有一个a函数的声明
与一个a的赋值,函数没有调用不会直接执行,但是执行到a=10时,系统
会去找a的地址(找不就gg,undefinded是定义了没赋值),又由于作用域链
的查找顺序是由里向外的,故要先从函数b里面开始查找,在查找的过程
中,发现函数b中已经声明了一个函数名为a的函数(重名问题!),所以
查找到函数名为a的函数后,这里便不再往外查找,所以这里的a=10其实
是将10赋值给了函数名为a的这个函数对象(函数a在声明时也有一块自
己的内存空间),所以最后在console时,a=1(没有修改到这个全局变量
a,a=10操作作用到了另一个内存空间上了)。
1 | function b(){ |
去除函数a,得到的就是10了。
这里在函数b里的作用域里没有查找到名为a的对象或者变量,那么继续向外查找,发现在全局作用域里发现了有变量a的内存地址,于是将10这个值赋值给了全局变量a。
1 | var a; function a(){ console.log(10); } console.log(a); |