JS的解析与执行过程—全局预处理阶段之命名冲突的处理策略
Posted 晨雾歌谣
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JS的解析与执行过程—全局预处理阶段之命名冲突的处理策略相关的知识,希望对你有一定的参考价值。
有如下代码:
1 <body> 2 <script> 3 alert(f); 4 5 function f() { 6 console.log("fff"); 7 } 8 var f = 5; 9 </script> 10 </body>
不论var f 与function f 的先后顺序如何,该代码执行的结果总是弹出function f 的字符串,为什么呢?像这种函数与变量命名冲突时JS的处理原则又是什么?
在扫描函数声明与变量声明的时候,是先扫描函数声明(function fn()),后扫描变量声明(var a)的;
- 处理函数声明有冲突,会覆盖;
- 处理变量声明有冲突,会忽略;
上面代码中,由于先扫描函数声明,所以LexicalEnviroment对象中先存在了 f 指向函数的引用,然后扫描到变量的时候发现变量名冲突,忽略这个变量,所以总是弹出函数字符串。
也就是说,在JS中函数的优先级是高于变量的。相同优先级以后面的为准,不同优先级以级别高的为准。
然后当存在两个同名函数时,会覆盖,所以总是指向后一个函数的,这点就像声明两个同名变量一样。
总结:有如下代码:
1 <script> 2 alert(a); 3 // alert(b); 4 alert(f); 5 alert(g); 6 7 var a = 5; 8 b = 6; 9 alert(b); 10 function f() { 11 console.log("fff"); 12 } 13 var g = function() { 14 console.log("ggg"); 15 } 16 alert(g); 17 </script>
这段代码在预处理阶段,分别扫描函数声明和变量声明,加入到全局对象window中:
1 window = { 2 f: 函数引用, 3 a: undefined, 4 g: undefined 5 }
注意,由于函数 g 是以函数表达式的方式声明的,所以在预处理时会当作一个变量,其值为undefined,所以上面代码执行结果为弹出undefined, f 的字符串表示, undefined
然后走过了var a = 5; b = 6;之后window对象变为:
1 window = { 2 f: 函数引用, 3 a: 5, 4 b: 6, 5 g: undefined 6 }
所以此时alert(b)弹出6;
因为在JS中不用var声明,直接写的变量默认为全局变量(window的),此时直接不用预处理而直接一步加到全局对象中,预处理的undefined被赋值。
然后走过函数f与函数g的表达式,此时g也指向函数,所以最后alert(g)弹出g的字符串。
以上是关于JS的解析与执行过程—全局预处理阶段之命名冲突的处理策略的主要内容,如果未能解决你的问题,请参考以下文章