全局作用域与局部作用域之迷思:
这一段知识点的学习可能会让不少小伙伴头大,现将个人见解奉上,欢迎探讨。
先看一段代码:
此时执行结果为123
原因如下:
正常来讲程序自上往下执行,小伙伴可能会向,为什么函数执行会在它被声明之前呢,这样不会报错吗?答案是不会报错。此处涉及到函数提升的问题,也就是说,虽然function是在被执行的位置之后定义,但JS实际运行时会首先将它提升到顶部,所以此处函数仍可正常执行。
运行过程分析:
1.声明变量 a = 123;
2.将变量a传递给fn并执行fn,此时函数内a的值变为456.
3.向控制台打印a,结果为123
很多同学会有疑问,函数内部对变量a进行了操作,但为什么打印结果是123而不是456呢,这要分两部分来分析:
1.全局作用域中的a与局部作用域中的a并非是同一个变量,只不过是他们的变量名称恰好相同而已,function fn(a){}小括号中的a相当于是在fn的局部作用域中声明了一个变量a,外部环境实际上是无法直接访问到这个变量的。
2在执行过程中,fn(a); 中的a是实参,也就是全局变量a,将全局变量a的值123传递到函数fn中,fn的局部变量a接收到这个数 ,然后执行a = 456,那么函数中的局部变量a的值由123就变为了456。但console.log(a); 是在全局环境中执行的,我们之前说过了,全局环境不能直接访问局部环境。所以console.log访问的仍然是全局变量a,所以打印值仍然是123。
此处将全局变量和局部变量同时命名为a可能会造成理解上的难度,我们将代码改成如下:
b is not defined ,说明在全局作用域中它不能被访问到。
我们再将代码小小调整一下:
实际上,全局虽然无法直接访问局部变量,但局部变量是可以向上访问它的父级的变量的,此处fn的父级即为全局作用域,所以在fn中console.log(a)时可以拿到a的值。
我们继续调整代码:
此段代码与第一段代码的不同之处是,标红的fn()小括号中没有a,也就是说,此时fn中未对a进行声明我们便在函数中使用了它,那么此处的a便默认是全局变量,大家会发现有两个全局变量a,函数的执行是在var a =123 之后进行的,若有两个同名全局变量,后执行的会覆盖先执行的。所以两次打印结果都是456。
再来一次调整:
我们将var a = 123 和fn(a) 互换了位置,执行结果发生了变化,此处也反应了先后顺序对执行结果的影响。