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 { } ...
随机推荐
- 【JS】怎样用原生JS实现jQuery的ready方法
Jquery中$(document).ready()的作用类似于传统JavaScript中的window.onload方法,只是与window.onload方法还是有差别的. 总的来说,window. ...
- linux线程间同步(1)读写锁
读写锁比mutex有更高的适用性,能够多个线程同一时候占用读模式的读写锁.可是仅仅能一个线程占用写模式的读写锁. 1. 当读写锁是写加锁状态时,在这个锁被解锁之前,全部试图对这个锁加锁的线程都会被堵塞 ...
- jni传递对象中包含arraylist对象。
相信在使用jni的过程中,总是要传递各种各样的类型,在这其中,我也碰到了一些问题. 简单的传一些内容,相信在网上一搜一大把. 所以我们就来说说.传递对象中包含arraylist吧. 在这里先给大家一个 ...
- python-网络-udp
python-网络-udp 标签(空格分隔): python 开发环境:windows Pycharm+python3.* 工具:网络调试助手 UDP[client]-发送数据 from socket ...
- 002.ES2015和ES2016新特性--箭头函数.md
1. ES2015中的箭头函数 JavaScript有一级函数的特性,也就是说,函数像其他值一样可以当成参数传来传去. var result = [1,2,3].reduce(function(tot ...
- OpenGL编程(三)让矩形动起来
上次实现了在窗口中添加一个了一个矩形.这次的任务是在上次代码的基础上,让那个矩形动起来. 1.思路 要看到动态的效果,首先添加一个定时器,规定的时间刷新一次窗口:不断修改矩形的位置,使其在时间轴上达到 ...
- dedecms4张关键表解析之2
4张核心表的具体情况: 1.第一张表:dede_arctype 栏目表 字段解析: topid:上一级的id(0表示为顶级,1表示为下一级....) typename: 栏目名称 typedir:栏 ...
- 【Git 五】TortoiseGit中SSH密钥的配置方法
注意:我用的 TortoiseGit 版本是 2.6 的. 一.找到安装目录下的 bin 目录 二.点击 puttygen.exe 三.点击 Generate 生成完毕之后,将 public key ...
- 编码问题异常处理:UnicodeDecodeError: 'gbk' codec can't...
作为编码问题集合: 2)UnicodeDecodeError: 'utf-8' codec can't decode byte 0xbd in position 0: invalid start by ...
- JAVA利用反射映射JSON对象为JavaBean
关于将JSONObject转换为JavaBean,其实在JSONObject中有对于的toBean()方法来处理,还可以根据给定的JsonConfig来处理一些相应的要求,比如过滤指定的属性 //返回 ...