JavaScript的执行上下文
JavaScript的执行上下文
JavaScript的执行上下文一、执行上下文的理解
每个执行上下文都与一个作用域链(scope chain)关联起来。该作用域链用来在function执行时求出标识符(identifier)的值。该链中包含多个对象,在对标识符进行求值的过程中,会从链首的对象开始,然后依次查找后面的对象,直到在某个对象中找到与标识符名称相同的属性。在每个对象中进行属性查找时,会使用该对象的prototype链。在一个执行上下文中,与其关联的作用域链只会被with语句和catch 子句影响。
活动的执行上下文组在逻辑上组成一个堆栈。堆栈底部永远都是全局上下文(global context),而顶部就是当前(活动的)执行上下文。堆栈在执行上下文类型进入和退出上下文的时候被修改(推入或弹出)。
二、在进入一个新的执行上下文时,会按顺序执行下面的操作
1、创建激活(activation)对象
激活对象是在进入新的执行上下文时创建出来的,并且与新的执行上下文关联起来。在初始化构造函数时,该对象包含一个名为arguments的属性。激活对象在变量初始化时也会被用到。JavaScript代码不能直接访问该对象,但可以访问该对象的成员(如 arguments)。
2、创建作用域链
接下来的操作是创建作用域链。每个 function 都有一个内部属性[[scope]],它的值是一个包含多个对象的链。该属性的具体值与 function 的创建方式和在代码中的位置有很大关系(见本建议后面介绍的“function 对象的创建方式”内容)。此时的主要操作是将上一步创建的激活对象添加到 function 的[[scope]]属性对应的链的前面。
3、变量初始化
这一步对function中需要使用的变量进行初始化。初始化时使用的对象是创建激活对象过程中所创建的激活对象,不过此时称做变量对象。会被初始化的变量包括 function 调用时的实际参数、内部function和局部变量。在这一步中,对于局部变量,只是在变量对象中创建了同名的属性,其属性值为undefined,只有在 function 执行过程中才会被真正赋值。全局JavaScript代码是在全局执行上下文中运行的,该上下文的作用域链只包含一个全局对象。
三、实例
1、例如,我们可以定义执行上下文堆栈是一个数组:
ECStack = [];
2、全局代码
这种类型的代码是在"程序"级处理的:例如加载外部的js文件或者本地<script></script>标签内的代码。全局代码不包括任何function体内的代码。
在初始化(程序启动)阶段,ECStack是这样的:
ECStack = [
globalContext
];
3、函数代码
当进入funtion函数代码(所有类型的funtions)的时候,ECStack被压入新元素。需要注意的是,具体的函数代码不包括内部函数(inner functions)代码。如下所示,我们使函数自己调自己的方式递归一次:
(function foo(bar){
if (bar)
{
return;
}
foo(true);
})();
那么,ECStack以如下方式被改变:
// 第一次foo的激活调用
ECStack = [
<foo> functionContext
globalContext
];
// foo的递归激活调用
ECStack = [
<foo> functionContext – recursively
<foo> functionContext
globalContext
];
每次return的时候,都会退出当前执行上下文的,相应地ECStack就会弹出,栈指针会自动移动位置,这是一个典型的堆栈实现方式。一个抛出的异常如果没被截获的话也有可能从一个或多个执行上下文退出。相关代码执行完以后,ECStack只会包含全局上下文(global context),一直到整个应用程序结束。
3、Eval 代码
eval函数调用的时候产生的上下文。eval(变量或函数声明)活动会影响调用上下文(calling context)。
eval('var x = 10');
(function foo() {
eval('var y = 20');
})();
alert(x); // 10
alert(y); // "y" 提示没有声明
ECStack的变化过程:
ECStack = [
globalContext
];
// eval('var x = 10');
ECStack.push(
evalContext,
callingContext: globalContext
);
// eval exited context
ECStack.pop();
// foo funciton call
ECStack.push(<foo> functionContext);
// eval('var y = 20');
ECStack.push(
evalContext,
callingContext: <foo> functionContext
);
// return from eval
ECStack.pop();
// return from foo
ECStack.pop();
- javascript中求二维数组最小值(javascript实现数组最大值和最小值的6种方法)
- 微信小程序抽签如何抽中(JavaScript实现班级抽签小程序)
- javascript数组实例扩展方法(JavaScript如何监测数组的变化)
- javascript里字符串描述(JavaScript字符串操作的四个实用技巧)
- js 定时切换图片(JavaScript定时器实现无缝滚动图片)
- javascript作用域实例(JavaScript defineProperty如何实现属性劫持)
- js中事件的三个阶段(JavaScript中事件冒泡机制示例详析)
- javascript如何实现异步任务(JavaScript 中如何实现并发控制)
- javascript如何转换int型(浅谈JavaScript中的parseInt的妙用)
- 生成随机数javascript(JavaScript实现随机生成验证码及校验)
- javascript编程中的promise(JavaScript如何利用Promise控制并发请求个数)
- jspromise原理(JavaScript使用promise处理多重复请求)
- javascript制作表格(JavaScript实现动态表格效果)
- javascript 模块原理(详解JavaScript引擎V8执行流程)
- javascript构造重复数组(JavaScript平铺数组转树形结构的实现示例)
- JavaScript 常用的开发规范
- 新晋小花被称女版吴卓羲 将取代滕丽名成为TVB新一代御用女警(新晋小花被称女版吴卓羲)
- 艺人吴卓羲10年警察生涯,演足10年阿Sir,系咩玩法(艺人吴卓羲10年警察生涯)
- 菲律宾潜水(菲律宾潜水价格)
- 泰国人妖(变性手术生殖器要割掉吗)
- 泰国美女(泰国人妖和女性如何区分)
- 泰国旅游业怎么样(泰国的旅游产业)
热门推荐
排行榜
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9