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怎么生成html控件(JavaScript+html实现前端页面滑动验证2)
- 在vs中设置Javascript的智能提示
- html注册表单验证代码(JavaScript+html实现前端页面随机二维码验证)
- js搜索功能的实现(前端JavaScript实现本地模糊搜索功能的方法实例)
- javascript函数工具有哪些(如何让你的JavaScript函数更加优雅详解)
- JavaScript 阻止超链接跳转的操作方法(多种写法)(JavaScript 阻止超链接跳转的操作方法多种写法)
- js淘宝购物车效果代码(JavaScript实现电商平台商品细节图)
- js实时获取页面宽度(JavaScript获取网页的宽高及如何兼容详解)
- javascript如何操作文档元素(JavaScript操作元素实例大全)
- ASP.NET使用JavaScriptSerializer实现序列化与反序列化
- js中什么是宏任务(浅谈JavaScript宏任务和微任务执行顺序)
- 浏览器怎么显示javascript页面(JavaScript如何通过userAgent判断几个常用浏览器详解)
- JavaScript的执行上下文
- js宏任务都有哪些(JavaScript 操作宏任务与微任务)
- js闭包可以解决哪些问题(JavaScript中let避免闭包造成问题)
- JavaScript将具有父子关系的数据转化成树形结构,供tree控件使用
- 休闲VS新古典 办公家居简约设计(办公家居简约设计)
- 15个新成 园 位置公布 深圳龙岗2022年共建花园建设又有大动作(15个新成园位置公布)
- 记者手记 书记带我去 巡街(记者手记书记带我去)
- 富士胶片集团将向土耳其东南部地震灾民捐赠5000万日元 | 美通社(富士胶片集团将向土耳其东南部地震灾民捐赠5000万日元)
- 二次创业 的富士胶片,在进博会上首次展示完成转型后的全线医疗产品(二次创业的富士胶片)
- 富士胶片 中国 我们对上海的信心没有任何改变(富士胶片中国)
热门推荐
- laravel设置读写权限(解决laravel上传图片之后,目录有图片,但是访问不到404的问题)
- vue各组件如何引用(Vue局部组件数据共享Vue.observable的使用)
- dedecms5.7使用教程(dedecms v5.7提示php.ini register_globals must is Off错误的解决方法)
- ftp上传工具使用方法(CuteFTP多线程FTP上传下载工具功能介绍)
- mysql查询条件的优化(MySQL查询优化之查询慢原因和解决技巧)
- css3旋转动画教学(css3动画效果抖动解决方法)
- python下划线怎么用(Python3中_下划线和__双下划线的用途和区别)
- docker镜像配置教程(给Docker更换国内镜像源操作)
- mysql中null的用法(为什么mysql字段要使用NOT NULL)
- ftp软件filezilla安装不了(filezilla连不上FTP服务器的解决方法)
排行榜
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9