高能预警:执行上下文及执行栈

2021-01-27 15:56:15 浏览数 (2)

什么是执行上下文?

其实,执行上下文,只是一个比较抽象的概念,待我慢慢道来。

打个比方:比如你尿急,是不是得上厕所。尿急是一个动作,就相当于我们的程序代码,那么厕所是不是一个环境,你总不能随地大小便吧。所以这个环境就是指我们程序执行的环境,从抽象层面上讲就是你的给程序代码一个可以执行环境。

比较专业的术语如下:

简而言之,执行上下文是评估和执行 JavaScript 代码的环境的抽象概念。每当 Javascript 代码在运行的时候,它都是在执行上下文中运行。

执行上下文的类型

一般分为三种:

  • 全局执行上下文:一般是指向 window 对象,一个程序只有一个全局上下文,指在浏览器的情况下。
  • 函数执行上下文:每当函数执行的时候,都会创建一个属于函数的上下文执行环境,但是函数的执行上下文,可以有多个,因为函数里面还可以再嵌套函数。
  • eval执行上下文:平常不是很常用,我们不准备讲。

执行栈

可以这么理解,执行栈就是一个队列,就好像我们放羽毛球进羽毛球桶一样,总是先放进去的只能后面使用,后放进去的先使用。

执行栈的目的就是用来存储我们前面所说的各种执行上下文。

js 引擎在执行代码的时候,会先执行放在执行栈前面的执行上下文,执行完就会释放掉,继续执行其他执行上下文,直到全局执行上下文执行完毕。

先来看一段代码:

代码语言:javascript复制
let a = 'Hello World!';

function first() {
  console.log('Inside first function');
  second();
  console.log('Again inside first function');
}

function second() {
  console.log('Inside second function');
}

first();
console.log('Inside Global Execution Context');

我们先来解析一下整个流程:第一步:首先是创建执行上下文 js 引擎在执行脚本的时候,会先创建全局执行上下文,压入执行栈底部 然后碰到 first() 函数创建 first 函数执行上下文,将其压入执行栈中。

first() 执行时,碰到 second() 函数创建 second 函数执行上下文,将其压入执行栈中。

第二步:执行代码 首先先是执行 first() 碰到 second() 执行,所以 second() 函数执行完毕销毁,再到 first() 函数执行完毕销毁,最后再到 全局执行完毕

代码语言:javascript复制
// 打印顺序如下
Inside first function
Inside second function
Again inside first function
Inside Global Execution Context

怎么创建执行上下文?

创建执行上下文有两个阶段:1) 创建阶段 和 2) 执行阶段。

  • this 值的决定,即我们所熟知的 This 绑定。
  • 创建词法环境组件。
  • 创建变量环境组件。
代码语言:javascript复制
ExecutionContext = {
  ThisBinding = <this value>,
  LexicalEnvironment = { ... },
  VariableEnvironment = { ... },
}

This 绑定:

在全局执行上下文中,this 的值指向全局对象。(在浏览器中,this引用 Window 对象)。在函数执行上下文中,this 的值取决于该函数是如何被调用的。如果它被一个引用对象调用,那么 this 会被设置成那个对象,否则 this 的值被设置为全局对象或者 undefined(在严格模式下)。例如:

代码语言:javascript复制
let foo = {
  baz: function() {
  console.log(this);
  }
}

foo.baz();   // 'this' 引用 'foo', 因为 'baz' 被
             // 对象 'foo' 调用

let bar = foo.baz;

bar();       // 'this' 指向全局 window 对象,因为
             // 没有指定引用对象

0 人点赞