JS的解析与执行过程—(全局预处理阶段)
Posted 晨雾歌谣
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JS的解析与执行过程—(全局预处理阶段)相关的知识,希望对你有一定的参考价值。
问题:有如下代码
1 var a = 1; 2 function pop() { 3 alert(a); 4 var a = 5; 5 } 6 pop();//执行结果,弹出undefined
这段代码的执行结果为undefined,为什么呢?
JS的解析与执行并不是读一行,处理一行,读一行,处理一行这样进行的,而是分为两个阶段:
1、预处理阶段;
2、执行阶段;
然后分别以全局和函数内部的局部代码而言:
1、全局预处理
在解析JS代码的时候,首先会创建一个全局LexicalEnviroment{ }(词法环境)对象
接下来扫描JS代码里面的两个部分:
a、用声明的方式创建的函数;
b、用var定义的变量;
扫面完毕后将这些变量及函数添加到全局的词法环境对象里面去;
1 LexicalEnviroment: { 2 a: undefined, 3 b: undefined, 4 test: 对函数的一个引用 5 } 6 7 //用声明的方式创建的函数 8 function test(params) { 9 10 } 11 //用函数表达式创建的函数 12 var test1 = function(params) { 13 14 } 15 //用var定义的变量 16 var a = 5; 17 var b; 18 //其他变量 19 c = 6;
定义一个声明函数和一个函数表达式来证明这一点,代码如下:
1 f(); 2 g(); 3 4 function f() { 5 console.log("ff"); 6 } 7 var g = function() { 8 console.log("gg"); 9 }
得到如下结果:
1 ff 2 e:Codejavascriptday03 est2.js:2 3 g(); 4 ^ 5 6 TypeError: g is not a function
函数f被正常执行,而函数g报错了
因为在预处理阶段,函数f的引用被放在LexicalEnviroment对象中了,而g没有,所以在调用时函数g()并不存在,所以报错。
改一下位置,这样就对了
1 f(); 2 var g = function() { 3 console.log("gg"); 4 } 5 g(); 6 7 function f() { 8 console.log("ff"); 9 }
这点在var定义变量上的体现:
1 console.log(a); 2 console.log(b); 3 4 var a = 5; 5 b = 6;
这段代码的执行结果如下:
1 undefined 2 e:CodeJavaScriptday03 est3.js:2 3 console.log(b); 4 ^ 5 6 ReferenceError: b is not defined
可见,如上所说,以var方式定义的a被添加到全局LexicalEnviroment{ }(词法环境)对象中了,其值为undefined,而直接定义的b此时不存在,所以报错。
这就是全局预处理阶段的过程。
声明:
关于全局的词法环境对象LexicalEnviroment,在浏览器中就约等于window对象,该对象是属于JS解析器的东西,在不同的地方叫法不同,比如在Node中称为Execute Context(运行上下文对象)或许更合适一点,在ECMA -262标准中有其解释,但我们无需关心其具体含义,只是有这个概念便可。
以上是关于JS的解析与执行过程—(全局预处理阶段)的主要内容,如果未能解决你的问题,请参考以下文章