问题:有如下代码

 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的解析与执行过程—全局预处理阶段之全局词法环境对象的更多相关文章

  1. JS的解析与执行过程—函数预处理

    声明:之所以分为全局预处理与函数预处理,只是为了理解方便,其实在实际运行中二者是不分先后的. 函数预处理阶段与全局预处理的差别: 函数每调用一次,就会产生一个LexicalEnviroment对象,在 ...

  2. JS的解析与执行过程

    JS的解析与执行过程 全局中的解析和执行过程 预处理:创建一个词法环境(LexicalEnvironment,在后面简写为LE),扫描JS中的用声明的方式声明的函数,用var定义的变量并将它们加到预处 ...

  3. JS的解析与执行过程—全局预处理阶段之命名冲突的处理策略

    有如下代码: <body> <script> alert(f); function f() { console.log("fff"); } var f = ...

  4. js全局的解析与执行过程

    先看下面实例的执行结果: alert(a);//undefined alert(b);//报错 alert(f);//输出f函数字符串 alert(g);//undefined var a = 1; ...

  5. js函数的解析与执行过程

    function f(a,b,c){ alert(a);//函数字符串 alert(b); var b = 5; function a(){ } } f(1,2); //预处理 lexicalEnvi ...

  6. JS引擎线程的执行过程的三个阶段(二)

    继续JS引擎线程的执行过程的三个阶段(一) 内容, 如下: 三. 执行阶段 1. 网页的线程 永远只有JS引擎线程在执行JS脚本程序,其他三个线程只负责将满足触发条件的处理函数推进事件队列,等待JS引 ...

  7. JS引擎线程的执行过程的三个阶段(一)

    浏览器首先按顺序加载由<script>标签分割的js代码块,加载js代码块完毕后,立刻进入以下三个阶段,然后再按顺序查找下一个代码块,再继续执行以下三个阶段,无论是外部脚本文件(不异步加载 ...

  8. openWRT自学---基于backfire版本,分析其Make命令的执行过程和各阶段的主要产物

    准备阶段:从SVN下载backfire的编译环境(位置是:svn co svn://svn.openwrt.org/openwrt/branches/backfire),然后按照openWRT的要求, ...

  9. js的解析--预处理(三)

    js的解析与执行过程  分全局  {预处理阶段和执行阶段}  函数{预处理函数和执行阶段}   1/创建词法环境(环境上下文) LexicalEnvironment   === window { } ...

随机推荐

  1. JBOSS部署项目之后,无法通过IP地址訪问,仅仅能通过localhost或者127.0.0.1訪问

    这几天入职到了一家新的公司,然后第一天就開始搭建各种环境.由于原先一直用的是Tomcat容器,然后也是第一次接触JBOSS容器,搭建完之后,在MyEclipse中启动了JBOSS容器,然后想在浏览器中 ...

  2. xcode5. 安装cocos2d-x 学习中。。。

    找了一些帖子  没搞出来,后来找到原因了   如今的cocos2d版本号在xcode.5上 没右模版了. 用命令行 来运行.看了官方的文档.最终攻克了--- 对于自己解决的问题都会感到点兴奋. .. ...

  3. mysql-过程与函数

    一.过程与函数简介 过程与函数是命名的PL/SQL块(也是用户的方案对象),被编译后存储在数据库中,以备执行.因此,其他PL/SQL块可以按名称来使用他们.所以可以将商业逻辑.企业规划写成函数或过程保 ...

  4. 一站式学习WireShark

    一 基础 http://blog.sina.com.cn/s/blog_987e00020102x5k1.html 选中一个数据包,右键选中某一个数据包,然后follow-->Tcp Strea ...

  5. 洛谷P1137 旅行计划 解题报告(拓扑排序+DP)

    我看了一下其他大佬的题解,大部分都是拓扑排序加上DP.那么我想有的人是不明白为什么这么做的,拓扑排序有什么性质使得可以DP呢?下面我就提一下. 对一个有向无环图(Directed Acyclic Gr ...

  6. Java类和对象8

    按要求编写Java应用程序. (1)创建一个叫做People的类: 属性:姓名.年龄.性别.身高         行为:说话.计算加法.改名 编写能为所有属性赋值的构造方法: (2)创建主类: 创建一 ...

  7. windos下安装多个mysql服务

    最近需要使用Mysql制造大量数据,需要多个Mysql服务器.一开始的解决方案是使用多个windows机器.实体机不够,则用虚拟机来搞.但,,,,安装多个虚拟机…….好吧, 在网上查了下,有使用单个机 ...

  8. js闭包实例展示

    准确来说,闭包是基于正常的垃圾回收处理机制下的.也就是说,一般情况一个函数(函数作用域)执行完毕,里面声明的变量会全部释放,被垃圾回收器回收.但闭包利用一个技巧,让作用域里面的变量,在函数执行完之后依 ...

  9. [USACO15JAN]草鉴定Grass Cownoisseur(分层图+tarjan)

    [USACO15JAN]草鉴定Grass Cownoisseur 题目描述 In an effort to better manage the grazing patterns of his cows ...

  10. WPF模仿QQ登录按钮

    原文:WPF模仿QQ登录按钮 如下图,第一张是未点击时按钮样式,第二张是鼠标划过时按钮样式. 样式代码: <Style TargetType="{x:Type Button}" ...