JavaScript执行环境
执行环境(Execution Context,也称为"执行上下文")是JavaScript中最为重要的一个概念。执行环境定义了变量或函数有权访问的其它数据,决定了各自的行为。当JavaScript代码执行的时候,会进入不同的执行环境,这些不同的执行环境就构成了执行环境栈。
JavaScript中主要存在三种执行环境:
- 全局执行环境
JavaScript代码执行的默认环境。通常被默认为window对象,所有的全局变量和函数都作为window对象的属性和方法存在。当执行环境中的代码执行完毕之后,执行环境被销毁,其中的所有变量和函数也随之销毁。对于全局执行环境来说,当关闭网页或浏览器时,该环境被销毁。
- 函数执行环境
当执行一个JavaScript函数时,函数的环境被推入环境栈中,执行完毕之后,栈将执行环境推出,将控制权转交给之前的执行环境。
- Eval环境
执行eval()函数时创建。
对于执行环境栈,请看如下代码:
var a = "global";
function example(){
console.log(a);
} function outer(){
var b = "outer";
console.log(b); function inner(){
var c = "inner";
console.log(c);
example();
} inner();
} outer();
代码首先进入全局执行环境,然后依次进入outer,inner和example的执行环境,执行环境栈可以表示为:

每个执行环境都有三个重要的属性,变量对象(VO)、作用域链(scope chain)和this。下面首先看一下变量对象。
变量对象和活动对象(VO和AO)
变量对象
每个执行环境都有一个与之关联的变量对象(variable object),环境中定义的所有变量和函数都保存在这个对象中。当代码在一个环境中执行时,会创建当前变量对象的一个作用域链(scope chain)。作用域链的最前端,始终是当前执行环境的变量对象。如果执行环境是函数,则其活动对象(activation object)作为变量对象。作用域链的下一个变量对象来自于父执行环境,而再下一个变量对象来自于父环境的外部环境,以此类推构成完整的作用域链,而最外层的变量对象始终是全局执行环境的变量对象。
一般来说,变量对象(VO)中包含以下信息:
- 变量
- 函数声明
- 函数的形参
当JavaScript代码执行的时候,如果试图寻找一个变量或函数,就会首先寻找VO。对于前面提到的代码,全局执行环境的VO如下所示:

对于VO来说,函数表达式不包含在VO中,没有使用var声明的变量也不包含在VO中,这种方式只是给Global添加了一个属性。
活动对象
只有全局执行环境的变量对象允许通过VO的属性名称间接访问。但在函数执行环境中,VO是不允许被直接访问的。此时,由活动对象(Activation Object,简称AO)扮演VO的角色。活动对象在进入函数执行环境时被创建,它通过函数的arguments属性初始化,其中Arguments Objects是函数执行环境中活动对象AO的内部对象。
VO和AO的关系,简单点说就是,VO在不同的执行环境中有不同的变现形式。在全局执行环境中,可以直接使用VO;但是在函数执行环境中,AO被创建。
在上面的代码例子中,当开始执行outer函数的时候,outer函数的AO被创建如下图所示:

执行环境的具体过程
当进入一个执行环境的时候,JavaScript解释器会创建新的执行环境,但具体是怎么做的呢?主要分为两个阶段:
- 创建阶段
- 创建作用域链
- 创建VO/AO
- 设置this的值
- 执行阶段
- 设置变量的值
- 设置函数的引用
- 解释执行代码
对于"创建VO/AO"这一步,JavaScript解释器主要做了下面的事情:
- 根据函数参数,创建并初始化arguments object
- 根据函数内部代码查找函数声明
- 对于找到的所有函数声明,将函数名和引用全部存入VO/AO
- 如果存在同名函数,进行覆盖
- 根据函数内部代码查找变量声明
- 对于找到的所有变量声明,全部存入VO/AO,并初始化为"undefined"
- 如果变量名称和已经声明的形参或函数相同,那么变量声明不会干扰这类属性
看下面的例子:
function example(p) {
var a = 'hello';
var b = function b() {...};
function c() {...}
}
example(2);
对于上面的例子,在执行环境创建阶段,会得到如下的执行环境对象:
exampleExecutionContext={
scopeChain: {...},
VO:{
arguments:{
0:2,
length:1
}
p:2,
c:pointer to function c()
a:undefined,
b:undefined
},
this: {...}
}
在代码执行阶段,环境对象会被更新,如下所示:
exampleExecutionContext={
scopeChain: {...},
VO:{
arguments:{
0:2,
length:1
}
p:2,
c:pointer to function c()
a:'hello',
b:pointer to function b()
},
this: {...}
}
JavaScript执行环境的更多相关文章
- javascript执行环境(执行期上下文)详解
javascript执行环境(执行期上下文) 当js控制器(control)进入可执行代码时,控制器会进入一个执行环境,活动的多个执行环境构成执行环境栈,最上面的是正在运行的执行环境,当控制器进入一个 ...
- JavaScript 执行环境、作用域、内存管理及垃圾回收机制
前言 JavaScript具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中使用的内存. [原理]找出那些不再继续使用的变量,然后释放其占用的内存.为此,垃圾收集器会按照固定的时间间隔( ...
- Javascript 执行环境及作用域
执行环境是javascript中最为重要的一个概念. 执行环境定义了变量或函数有权访问的其他数据,决定了他们各自的行为. 每个执行环境都有一个与之关联的变量对象(variable object),环境 ...
- 【原】javascript执行环境及作用域
最近在重读<javascript高级程序设计3>,觉得应该写一些博客记录一下学习的一些知识,不然都忘光啦.今天要总结的是js执行环境和作用域. 首先来说一下执行环境 一.执行环境 书上概念 ...
- 图解JavaScript执行环境结构
JavaScript引擎在开始编译代码的时候,会对JavaScript代码进行一次预编译,生成一个执行环境,比如如下代码: window.onload=function(){ function sub ...
- DOM笔记(八):JavaScript执行环境和垃圾收集
一.执行环境 在有关于JavaScript对象或者this的指向问题时,脱离不了的另外一个概念就是执行环境,即上下文环境.执行环境在JavaScript是一个 很重要的概念,因为它定义了变量或函数有权 ...
- javascript 执行环境,变量对象,作用域链
前言 这几天在看<javascript高级程序设计>,看到执行环境和作用域链的时候,就有些模糊了.书中还是讲的不够具体. 通过上网查资料,特来总结,以备回顾和修正. 要讲的依次为: EC( ...
- JavaScript 执行环境(执行上下文) 变量对象 作用域链 上下文 块级作用域 私有变量和特权方法
总结自<高程三>第四章 理解Javascript_12_执行模型浅析 JS的执行环境与作用域 javascript高级程序第三版学习笔记[执行环境.作用域] 在javascript ...
- JavaScript——执行环境、变量对象、作用域链
前言 这几天在看<javascript高级程序设计>,看到执行环境和作用域链的时候,就有些模糊了.书中还是讲的不够具体.通过上网查资料,特来总结,以备回顾和修正. 目录: EC(执行环境或 ...
随机推荐
- postgresql无法安装pldbgapi的问题
要对函数进行调试需要安装插件pldbgapi,当初在windows上面的postgresql实例中执行了一下语句就安装上了: create extension pldbgapi; 但是在linux中执 ...
- MongoDB学习笔记五—查询上
数据准备 { , "goods_name" : "KD876", "createTime" : ISODate("2016-12- ...
- Linux下用netstat查看网络状态、端口状态(转)
转:http://blog.csdn.net/guodongdongnumber1/article/details/11383019 在linux一般使用netstat 来查看系统端口使用情况步. ...
- 一步步开发自己的博客 .NET版(3、注册登录功能)
前言 这次开发的博客主要功能或特点: 第一:可以兼容各终端,特别是手机端. 第二:到时会用到大量html5,炫啊. 第三:导入博客园的精华文章,并做分类.(不要封我) 第四:做 ...
- [PHP源码阅读]count函数
在PHP编程中,在遍历数组的时候经常需要先计算数组的长度作为循环结束的判断条件,而在PHP里面对数组的操作是很频繁的,因此count也算是一个常用函数,下面研究一下count函数的具体实现. 我在gi ...
- [DeviceOne开发]-手势动画示例分享
一.简介 这是iOS下的效果,android下完全一致.通过do_GestureView组件和do_Animation组件,deviceone能很容易实现复杂的跨平台纯原生动画效果,这个示例就是通过手 ...
- 菜鸟在C语言编译,链接时可能遇到的两个问题
最近在看 CSAPP (Computer Systems A Programmers Perspective 2nd) 的第七章 链接.学到了点东西,跟大家分享.下文中的例子都是出自CSAPP第七章. ...
- 如何在高并发分布式系统中生成全局唯一Id
月整理出来,有兴趣的园友可以关注下我的博客. 分享原由,最近公司用到,并且在找最合适的方案,希望大家多参与讨论和提出新方案.我和我的小伙伴们也讨论了这个主题,我受益匪浅啊…… 博文示例: 1. ...
- 向Java技术进军
前两天有个朋友要我帮忙写个打印机服务,要求能应用在.net .Dephi.和java程序上面.看了下需求不难也就串口操作,所以就在周未写了个Win32的动态库,对于一个曾经写MFC程序的.net程序员 ...
- 复化梯形求积分——用Python进行数值计算
用程序来求积分的方法有很多,这篇文章主要是有关牛顿-科特斯公式. 学过插值算法的同学最容易想到的就是用插值函数代替被积分函数来求积分,但实际上在大部分场景下这是行不通的. 插值函数一般是一个不超过n次 ...