JS的解析与执行过程—全局预处理阶段之全局词法环境对象
问题:有如下代码
var a = 1;
function pop() {
alert(a);
var a = 5;
}
pop();//执行结果,弹出undefined
这段代码的执行结果为undefined,为什么呢?
JS的解析与执行并不是读一行,处理一行,读一行,处理一行这样进行的,而是分为两个阶段:
1、预处理阶段;
2、执行阶段;
然后分别以全局和函数内部的局部代码而言:
1、全局预处理
在解析JS代码的时候,首先会创建一个全局LexicalEnviroment{ }(词法环境)对象
接下来扫描JS代码里面的两个部分:
a、用声明的方式创建的函数;
b、用var定义的变量;
扫面完毕后将这些变量及函数添加到全局的词法环境对象里面去;
LexicalEnviroment: {
a: undefined,
b: undefined,
test: 对函数的一个引用
}
//用声明的方式创建的函数
function test(params) {
}
//用函数表达式创建的函数
var test1 = function(params) {
}
//用var定义的变量
var a = 5;
var b;
//其他变量
c = 6;
定义一个声明函数和一个函数表达式来证明这一点,代码如下:
f();
g(); function f() {
console.log("ff");
}
var g = function() {
console.log("gg");
}
得到如下结果:
ff
e:\Code\JavaScript\day03\test2.js:2
g();
^ TypeError: g is not a function
函数f被正常执行,而函数g报错了
因为在预处理阶段,函数f的引用被放在LexicalEnviroment对象中了,而g没有,所以在调用时函数g()并不存在,所以报错。
改一下位置,这样就对了
f();
var g = function() {
console.log("gg");
}
g(); function f() {
console.log("ff");
}
这点在var定义变量上的体现:
console.log(a);
console.log(b); var a = 5;
b = 6;
这段代码的执行结果如下:
undefined
e:\Code\JavaScript\day03\test3.js:2
console.log(b);
^ ReferenceError: b is not defined
可见,如上所说,以var方式定义的a被添加到全局LexicalEnviroment{ }(词法环境)对象中了,其值为undefined,而直接定义的b此时不存在,所以报错。
这就是全局预处理阶段的过程。
声明:
关于全局的词法环境对象LexicalEnviroment,在浏览器中就约等于window对象,该对象是属于JS解析器的东西,在不同的地方叫法不同,比如在Node中称为Execute Context(运行上下文对象)或许更合适一点,在ECMA -262标准中有其解释,但我们无需关心其具体含义,只是有这个概念便可。
JS的解析与执行过程—全局预处理阶段之全局词法环境对象的更多相关文章
- JS的解析与执行过程—函数预处理
声明:之所以分为全局预处理与函数预处理,只是为了理解方便,其实在实际运行中二者是不分先后的. 函数预处理阶段与全局预处理的差别: 函数每调用一次,就会产生一个LexicalEnviroment对象,在 ...
- JS的解析与执行过程
JS的解析与执行过程 全局中的解析和执行过程 预处理:创建一个词法环境(LexicalEnvironment,在后面简写为LE),扫描JS中的用声明的方式声明的函数,用var定义的变量并将它们加到预处 ...
- JS的解析与执行过程—全局预处理阶段之命名冲突的处理策略
有如下代码: <body> <script> alert(f); function f() { console.log("fff"); } var f = ...
- js全局的解析与执行过程
先看下面实例的执行结果: alert(a);//undefined alert(b);//报错 alert(f);//输出f函数字符串 alert(g);//undefined var a = 1; ...
- js函数的解析与执行过程
function f(a,b,c){ alert(a);//函数字符串 alert(b); var b = 5; function a(){ } } f(1,2); //预处理 lexicalEnvi ...
- JS引擎线程的执行过程的三个阶段(二)
继续JS引擎线程的执行过程的三个阶段(一) 内容, 如下: 三. 执行阶段 1. 网页的线程 永远只有JS引擎线程在执行JS脚本程序,其他三个线程只负责将满足触发条件的处理函数推进事件队列,等待JS引 ...
- JS引擎线程的执行过程的三个阶段(一)
浏览器首先按顺序加载由<script>标签分割的js代码块,加载js代码块完毕后,立刻进入以下三个阶段,然后再按顺序查找下一个代码块,再继续执行以下三个阶段,无论是外部脚本文件(不异步加载 ...
- openWRT自学---基于backfire版本,分析其Make命令的执行过程和各阶段的主要产物
准备阶段:从SVN下载backfire的编译环境(位置是:svn co svn://svn.openwrt.org/openwrt/branches/backfire),然后按照openWRT的要求, ...
- js的解析--预处理(三)
js的解析与执行过程 分全局 {预处理阶段和执行阶段} 函数{预处理函数和执行阶段} 1/创建词法环境(环境上下文) LexicalEnvironment === window { } ...
随机推荐
- Android数据分批载入-滑动究竟部自己主动载入列表
Android数据分批载入-滑动究竟部自己主动载入列表 2014年5月9日 摘自:<Android高级开发实战-ui.ndk与安全> 本博文介绍怎样进行数据分批载入,在应用开发其中会常常使 ...
- 每一个程序猿都应该用MBP
换笔记本的想法非常久了.前段时间换工作就想看换工作之后是什么情况吧. 可能工作配的笔记本就是MBP.后来发现是想多了,新工作的笔记本是Thinkpad X240. 配置全然够用了,8G内存+128G的 ...
- P 值(p value)与统计检验
P 值是最常用的一个统计学指标,几乎统计软件输出结果都有P值. 统计学的观点,超过一定基准(比如 5%,其实是低于5%),就不能简单地认为这是偶然事件了,而是受到了外在的影响. 一般而言,为了确定从样 ...
- mac terminal终端怎么退出python命令行
>>>使用 quit(), exit(), 或者Command+d,或者Command+z退出命令行.
- [APIO2014]回文串 后缀自动机_Manancher_倍增
Code: // luogu-judger-enable-o2 #include <cstdio> #include <algorithm> #include <cstr ...
- TCP的连接管理
创建连接:(三次握手) 第一步: 客户端向服务器发送一个报文,该报文不含有数据段,SYN=1,随机产生sequence number(随机产生可用于避免某些安全性攻击) 第二步: 服务器收到报文,为这 ...
- shell单引号屏蔽变量方法
[goforit ~]$ name="玖零後大叔" [goforit~]$ echo $name 玖零後大叔 [goforit ~]$ echo "$name" ...
- 一个HelloWorld版的MySQL数据库管理器的设计与实现(源码)
2011年,实习期间写了一个简单的数据库管理器. 今天,特意整理了下,分享给大家. 有兴趣的同学,可以下载源码,瞧瞧. 源码只有4个类:LoginGUI,DatabaseGUI,Record,MySQ ...
- tt
Oracle报错处理 1.oem启动报错 解决方案:
- Unity Shader (二)Cg语言
一.Cg基本数据类型 float 32位浮点数 half 16位浮点数 int 32位整型 fixed 12位定点数 bool 布尔数据 simpler* 纹理对象的句柄( the handle to ...