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:\Code\JavaScript\day03\test2.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:\Code\JavaScript\day03\test3.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标准中有其解释,但我们无需关心其具体含义,只是有这个概念便可。

posted @   jixhua  阅读(355)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
点击右上角即可分享
微信分享提示