JavaScript内部原理系列-执行上下文(Execution Context)

概要

本文将向大家介绍ECMAScript的执行上下文以及相关的可执行代码类型。

定义

每当控制器到达ECMAScript可执行代码的时候,控制器就进入了一个执行上下文。
执行上下文(简称:EC)是个抽象的概念,ECMA-262标准中用它来区分不同类型的可执行代码。

标准中并没有从技术实现的角度来定义执行上下文的具体结构和类型;这是实现标准的ECMAScript引擎所要考虑的问题。

一系列活动的执行上下文从逻辑上形成一个栈。栈底总是全局上下文,栈顶是当前(活动的)执行上下文。当在不同的执行上下文间切换(退出的而进入新的执行上下文)的时候,栈会被修改(通过压栈或者退栈的形式)。

可执行代码类型

可执行代码类型和执行上下文相关。有的时候,当提到代码类型的时候,其实就是在说执行上下文。

举个例子,我们将执行上下文的栈以数组的形式来表示:

ECStask = [ ];

每次控制器进入一个函数(哪怕该函数被递归调用或者作为构造器),都会发生压栈的操作。内置eval函数工作的时候也不例外。

全局代码

这类代码是在“程序”级别上被处理的:比如,加载一个外部的js文件或者内联的js代码(被包含在<script></script>标签内)。全局代码不包含任何函数体内的代码。

在初始化的时候(程序开始),ECStack如下所示:

ECStack = [
    globalContext
];

函数代码

一旦控制器进入函数代码(各类函数),就会有新的元素会被压栈到ECStack。要注意的是:实体函数代码并不包括内部函数的代码。如下所示,我们调用一个函数,该函数递归调用自己一次:

(function foo(bar){
    if (bar){

    return;

}

foo(true);
})();

之后,ECStack就被修改成如下所示:

//首先激活foo函数
ECStack = [
     functionContext
    globalContext
];
//递归激活foo函数
ECStack = [
     functionContext - recursively
     functionContext
    globalContext
];

每次函数返回,退出当前活动的执行上下文时,ECStack就会被执行对应的退栈操作——先进后出——和传统的栈实现一致。同样的,当抛出未捕获的异常时,也会退出一个或者多个执行上下文,ECStack也会做相应的退栈操作。待这些代码完成之后,ECStack中就只剩下一个执行上下文(globalContext)——直到整个程序结束。

Eval代码

说到eval代码就比较有意思了。这里要提到一个叫做调用上下文的概念,比如:调用eval函数时候的上下文,就是一个调用上下文,eval函数中执行的动作(例如:变量声明或者函数声明)会影响整个调用上下文:

eval(‘var x = 10’);
(function foo(){
    eval(‘ var y = 20’);
})();
alert(x); // 10
alert(y); // ”y” is not defined

ECStack会被修改为:

ECStack = [
    globalContext
];
//eval(‘var x = 10’);
ECStack.push(
    evalContext,
    callingContext: globalContext
);

// eval exited context
ECStack.pop();

//foo function call
ECStack.push( functionContext);

//eval(‘ var y = 20’);
ECStack.push(
    evalContext,
    callingContext:  functionContext
);

//return from eval
ECStack.pop();

//return from foo
ECStack.pop();

在1.7以上版本SpiderMonkey的实现中(Firefox,Thunderbird浏览器内置的JS引擎),允许在调用eval函数的时候,将调用上下文作为第二个参数传递给eval函数。因此,如果传入的调用上下文存在的话,就有可能会影响该上下文中原有的私有变量(在该上下文中声明的变量):

function foo(){
    var x = 1;
    return function() { alert(x); }
};

var bar = foo();

bar(); // 1
eval(‘x = 2’, bar); //传递上下文,影响了内部变量“var x”
bar(); // 2

总结

这些基本理论对于后面执行上下文相关的细节(诸如变量对象、作用域链等等)分析是非常必要的。

扩展阅读

ECMA-363-3标准文档的对应的章节—— 10. 执行上下文

时间: 2024-10-13 10:37:55

JavaScript内部原理系列-执行上下文(Execution Context)的相关文章

深入理解Javascript之执行上下文(Execution Context)

在这篇文章中,将比较深入地阐述下执行上下文 - Javascript中最基础也是最重要的一个概念.相信读完这篇文章后,你就会明白javascript引擎内部在执行代码以前到底做了些什么,为什么某些函数以及变量在没有被声明以前就可以被使用,以及它们的最终的值是怎样被定义的.什么是执行上下文 Javascript中代码的运行环境分为以下三种: 全局级别的代码 - 这个是默认的代码运行环境,一旦代码被载入,引擎最先进入的就是这个环境. 函数级别的代码 - 当执行一个函数时,运行函数体中的代码. Eva

理解Javascript之执行上下文(Execution Context)

1>什么是执行上下文 Javascript中代码的运行环境分为以下三种: 全局级别的代码 - 这个是默认的代码运行环境,一旦代码被载入,引擎最先进入的就是这个环境. 函数级别的代码 - 当执行一个函数时,运行函数体中的代码. Eval的代码 - 在Eval函数内运行的代码. javascript是一个单线程语言,这意味着在浏览器中同时只能做一件事情.当javascript解释器初始执行代码,它首先默认进入全局上下文.每次调用一个函数将会创建一个新的执行上下文. 每次新创建的一个执行上下文会被添加

深入理解javascript执行上下文(Execution Context)

本文转自:http://blogread.cn/it/article/6178 在这篇文章中,将比较深入地阐述下执行上下文 - Javascript中最基础也是最重要的一个概念.相信读完这篇文章后,你就会明白javascript引擎内部在执行代码以前到底做了些什么,为什么某些函数以及变量在没有被声明以前就可以被使用,以及它们的最终的值是怎样被定义的. 什么是执行上下文 Javascript中代码的运行环境分为以下三种: 全局级别的代码 - 这个是默认的代码运行环境,一旦代码被载入,引擎最先进入的

JavaScript内部原理系列-变量对象(Variable object)

概要 我们总是会在程序中定义一些函数和变量,之后会使用这些函数和变量来构建我们的系统.然而,对于解释器来说,它又是如何以及从哪里找到这些数据的(函数,变量)?当引用一个对象的时候,在解释器内部又发生了什么? 许多ECMA脚本程序员都知道,变量和执行上下文是密切相关的: var a = 10; // 全局上下文中的变量 (function () { var b = 20; // 函数上下文中的局部变量 })(); alert(a); // 10 alert(b); // "b" is n

js笔记---作用域(执行上下文[execution context],活动对象) 闭包

(一)作用域: 首先,在javascript中的每个函数都是对象,是Funtion对象的一个实例,而Funtion中有一系列仅供javascript引擎存取的内部属性,其中一个便是[[scope]],它包含了一个函数被创建的作用域中对象的集合,这个集合就是函数的作用域链.当一个函数创建后,它的作用域链会被创建此函数的作用域中可访问的数据对象填充.例如定义下面这样一个函数: function add(num1,num2){var sum = num1+num2; return sum; } 在函数

JavaScript内部原理系列-闭包(Closures)

原文链接:http://www.faceye.net/search/142545.html 概要 本文将介绍一个在JavaScript经常会拿来讨论的话题 —— 闭包(closure).闭包其实已经是个老生常谈的话题了: 有大量文章都介绍过闭包的内容(其中不失一些很好的文章,比如,扩展阅读中Richard Cornford的文章就非常好), 尽管如此,这里还是要试着从理论角度来讨论下闭包,看看ECMAScript中的闭包内部究竟是如何工作的. 正如在此前文章中提到的,这些文章都是系列文章,相互之

JavaScript内部原理实践——真的懂JavaScript吗?(转)

通过翻译了Dmitry A.Soshnikov的关于ECMAScript-262-3 JavaScript内部原理的文章, 从理论角度对JavaScript中部分特性的内部工作机制有了一定的了解.但是,邓爷爷说过:“实践才是检验真理的唯一标准”.所以,我打算通过从内部原理来解释一些经常在笔试或者面试中遇到的关于JavaScript语言层面的题目来进一步学习和掌握JavaScript内部工作原理. 那么,首先就是要去找那些题目,google了一圈终于找到了来自Dmitry Baranovskiy的

JVM 内部原理系列

JVM 内部原理(一)- 概述 JVM 内部原理(二)- 基本概念之字节码 JVM 内部原理(三)- 基本概念之类文件格式 JVM 内部原理(四)- 基本概念之 JVM 结构 JVM 内部原理(五)- 基本概念之 Java 虚拟机官方规范文档,第 7 版 JVM 内部原理(六)- Java 字节码基础之一 JVM 内部原理(七)- Java 字节码基础之二 原文地址:https://www.cnblogs.com/kaleidoscope/p/9792619.html

Javascript 执行上下文 context&amp;scope

执行上下文(Execution context) 执行上下文可以认为是 代码的执行环境. 1 当代码被载入的时候,js解释器 创建一个 全局的执行上下文. 2 当执行函数时,会创建一个 函数的执行上下文. 3 当执行 eval()的时候,创建 一个 eval 执行上下文. # if,for,while 等块不会创建 execution context,从而不会创建 scope. 当js解释器开始工作的时候: 1 首先创建一个 执行上下文栈(后进先出) 2 接着创建一个 全局的执行上下文,并放入执