JavaScript中全局变量赋值后定义同名局部变量未修改全局变量的原因及内存机制解析
为什么执行myFunction1后全局变量a的值还是4?—— 解析JavaScript变量提升与作用域
兄弟,你遇到的这个问题核心就是JavaScript里的**变量提升(Hoisting)**机制,咱一步步拆解,看完你就彻底明白为啥结果是这样了。
先看myFunction1的执行过程
首先全局作用域里你声明了var a = 4,此时全局环境里的a就是4。当调用myFunction1()时,进入函数的局部作用域,JavaScript会先做一个关键操作:变量提升。
函数里的代码是这样的:
function myFunction1() { a= 5; var a= 6; }
但JavaScript在执行这个函数时,会先把所有var声明的变量“拎”到当前作用域的最顶部,相当于函数实际的执行顺序是这样的:
function myFunction1() { var a; // 变量提升:只声明,不赋值,此时a是undefined a = 5; // 给局部的a赋值为5 a = 6; // 再把局部的a改成6 }
看到没?整个函数里的a都是局部作用域里的变量,根本没碰全局的那个a。函数执行完之后,局部作用域被销毁,局部变量a也被回收,全局的a依然是最初的4,所以第一个alert(a)弹出4。
再对比myFunction2的情况
myFunction2里没有用var声明局部变量a,所以当执行a = 5时,JavaScript会向上查找作用域,找到全局的a并修改它的值。这就是为什么第二个alert(a)会弹出5——全局变量确实被修改了。
从内存运行机制层面解释
JavaScript的每个作用域对应一个执行上下文,每个执行上下文里都有一个变量对象(VO),用来存储当前作用域的变量:
- 全局执行上下文的VO里存储着全局变量
a,初始值是4。 - 当进入
myFunction1的执行上下文时,首先会创建函数的VO,先把所有var声明的变量加入这个VO(此时a的值是undefined)。 - 之后才会按代码顺序执行赋值操作,所有对
a的操作都是针对这个局部VO里的a,和全局VO里的a完全是两个独立的变量。 - 函数执行完毕,函数的执行上下文被销毁,局部VO里的
a也被垃圾回收,全局VO里的a自始至终没被修改过。
解答你的第二个疑问:为什么函数内的局部变量会“覆盖”对全局变量的预期修改?
还是因为变量提升!只要函数里用var声明了同名变量,这个声明就会被提升到函数作用域的顶部,相当于在函数内部,这个变量名已经被局部变量“占用”了。你写的a = 5其实是在给已经存在的局部变量赋值,根本轮不到全局变量。所以不管你在var a之前写多少次对a的赋值,都是在操作局部变量,自然不会影响全局的那个。
内容的提问来源于stack exchange,提问作者CodingFriend
相关产品推荐
相关产品推荐

