Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ECMAScript 之执行上下文 #22

Open
jejuin opened this issue Nov 20, 2020 · 0 comments
Open

ECMAScript 之执行上下文 #22

jejuin opened this issue Nov 20, 2020 · 0 comments

Comments

@jejuin
Copy link
Owner

jejuin commented Nov 20, 2020

执行上下文

执行上下文(Execution Context),也称为执行环境,就是当前 JavaScript 代码运行时所在环境的抽象概念。

每当开始执行代码时,JavaScript 引擎就会为整个程序创建一个执行上下文(全局执行上下文),JavaScript 代码都是在执行上下文中运行的。

在 JavaScript 中,执行环境主要分为:

  • 全局执行上下文(Global Execution Context): 全局执行上下文是最顶层的一个执行环境,是 JavaScript 代码最开始运行时的默认环境。一个程序中只会有一个全局执行上下文。
  • 函数执行上下文(Function Execution Context):在 JavaScript 中,每个函数都有自己的执行上下文。每当一个函数被调用时,就会为该函数创建一个新的执行上下文,函数执行结束之后,创建的函数执行上下文就会被销毁。
  • eval 函数执行上下文: eval 函数在执行其内部代码时,也会创建属于自己的执行上下文(因为 eval 函数并不建议使用,所以这里不做介绍)。

我们看一个例子:

var a = 'Hello World!'

function helloWorld () {
    var a = 'Hello Function!'
    console.log(a) 
}

helloWorld()
console.log('a) 

上述代码,创建的执行上下文结构如下图所示:
Image  7

显而易见,在一个 JavaScript 程序中,通常情况下都会存在多个执行上下文,那么这些执行上下文是如何管理的呢?

JavaScript 引擎创建了执行上下文栈(Execution Context Stack) 来管理执行上下文。,又称为调用栈。

调用栈是有大小的,当入栈的执行上下文超过一定数目,JavaScript 引擎就会报错,我们把这种错误叫做栈溢出。

执行上下文栈

首先我们来了解下什么是栈数据结构

栈中数据的存取方式类似给枪上子弹,先上的子弹最后打出,后上的子弹先打出。
特点:先进后出,后进先出

了解了栈数据结构后,我们继续来说执行上下文栈是如何管理执行上下文的?

我们用数组来模拟执行上下文栈的行为:ECStack = [];

function fn2() {
  console.log('fn2')
}

function fn1() {
  console.log('fn1')
  fn2();
}

fn1();

上述这段代码在执行过程中,执行上下文栈的行为是什么样的?我们来分析一下:

  1. 在代码开始执行时,首先会创建全局执行上下文并将其推入到执行上下文栈中;
ECStack.push(global_EC);
  1. 全局上下文入栈后,其中的可执行代码开始从顶部按顺序逐行解释执行,当调用函数 fn1时,会创建 fn1 函数执行上下文并将其推入到执行上下文栈中;
ECStack.push(fn1_EC);
  1. 以此类推,当开始执行 fn2 时,会创建 fn2 函数执行上下文并入栈;此时所有的执行上下文都已经入栈;
ECStack.push(fn2_EC);

Image  8

  1. 当 fn2 执行完毕,fn2 函数执行上下文出栈;
ECStack.pop();
  1. 当 fn1 执行完毕,fn1 函数执行上下文出栈;
ECStack.pop();
  1. 当所有代码执行完毕,就又回到了全局执行上下文;当程序退出时,即关闭浏览器或网页时,全局执行上下文才出栈。
ECStack.pop();

Image13

总结:

  • JavaScript 是单线程同步执行的,只有栈顶的上下文处于执行中,其他上下文需要等待;
  • 全局执行上下文永远第一个入栈,也就是说它永远在栈底;而当前执行的函数执行上下文永远最后一个入栈,也就是说它永远在栈顶。
  • 执行上下文出栈后,保存在该环境中的所有变量和函数定义也随之销毁。

参考:

JavaScript深入之执行上下文
前端基础进阶(二):执行上下文详细图解
JS 执行环境、作用域链、活动对象
The Journey of JavaScript From Downloading Scripts to Execution – Part III

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant