阅读理解:Understanding Execution Context and Execution Stack in Javascript

先贴原文地址:Understanding Execution Context and Execution Stack in Javascript
算是一个对 Javascript 基础的查漏补缺吧,内容主要包含 js 的执行上下文和执行栈。同样,并不是全文翻译,而是主要内容概括(就是搬运自己的阅读笔记 )。

执行上下文(Execution Context)

执行上下文 分为三类:

  • Global Execution Context:全局执行上下文。基础的执行上下文,所有不被包含在函数内部的代码均在全局执行上下文中。其主要做两件事情:创建一个全局对象(以浏览器环境为例则是 window 对象);设置this的值为该全局对象。全局执行上下文在程序中仅存在一个;
  • Functional Execution Context:函数执行上下文。当函数被执行时,一个函数执行上下文将会被创建。每一个函数都有其自己的函数执行上下文,但其仅函数在被执行或被调用的时候创建。函数执行上下文的可能存在多个;
  • Eval Function Execution Context:eval 函数执行上下文。其只存在于 eval 代码执行中,较为少见。

执行栈 / 调用栈(Execution Stack / Call Stack)

执行栈,也就是调用栈,以 LIFO 的形式被存储,存储了代码执行过程中所有的执行上下文。
直接看一个例子:

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');

执行栈
这个例子展示了执行栈在代码执行过程的变化,内容一目了然,就不在这里赘述了,接下来是一些更进阶的原理相关内容。

执行上下文是如何被创建的

执行上下文的创建分为两个阶段:

  1. Creation Phase
  2. Execution Phase

Creation Phase

创建阶段主要包含三部分工作:

  • Value of this is determined, also known as This Binding
  • LexicalEnvironment component is created
  • VariableEnvironment component is created

This binding

关键字 this 的绑定也就是确认 this 的引用对象,在 global context 中,this 指向 global 对象,在 function context 其指向调用函数的对象。 // 也就是 this 的基本规则

LexicalEnvironment component

根据 ES6 的官方声明,LexicalEnvironment 的定义如下:

A Lexical Environment is a specification type used to define the
association of Identifiers to specific variables and functions based
upon the lexical nesting structure of ECMAScript code. A Lexical
Environment consists of an Environment Record and a possibly null
reference to an outer Lexical Environment.

翻译过来就是:Lexical Environment(词汇环境?) 是一种规范的类型,其用于定义特定变量的标识符与基于ECMAScript代码词法嵌套结构函数之间的关联。Lexical Environment 由环境记录和外部词汇环境的可能空引用组成。// emmmmm…听起来很复杂
简单来讲:Lexical Environment 就是 标识符——变量 的 mapping 结构。(标识符指向 变量/函数 名,同时 变量 是对于真实对象的引用。) // 好吧,还是不懂

Lexical Environment 分为两个部分:

  • the environment record:环境记录就是变量和函数声明真实存储的地方;
  • a reference to the outer environment:对外部环境的引用意味着其能访问到父词法环境(作用域)

Lexical Environment 有两种,分别为:

  • global environment:对应着全局执行上下文,其没有外部环境,也就是对外部环境的引用为 null。其拥有 built-in 的 Object/Array/etc… 原型方法
  • function environment:用户定义的变量记录在 environment record 中,同时外部环境的引用可能为 global 可能为其他 function

environment record 也有两种,分别为:

  • Object environment record:定义 global context 中变量和函数的关联,对应着 global environment
  • Declarative environment record:存储变量/函数/参数,对应着 function environment

这里有一些伪代码来帮助你理解:

GlobalExectionContext = {
  LexicalEnvironment: {
    EnvironmentRecord: {
      Type: "Object",
      // Identifier bindings go here
    }
    outer: <null>
  }
}
FunctionExectionContext = {
  LexicalEnvironment: {
    EnvironmentRecord: {
      Type: "Declarative",
      // Identifier bindings go here
    }
    outer: <Global or outer function environment reference>
  }
}

Variable Environment

Variable Environment 也是一种 Lexical Environment,因此具有前述的所有性质。
ES6 中,两者的区别在于:Lexical Environment 存储函数声明和变量(let/const 的绑定),Variable Environment 只存储变量(var)的绑定。
看一个例子:

let a = 20;
const b = 30;
var c;
function multiply(e, f) {
 var g = 20;
 return e * f * g;
}
c = multiply(20, 30);

其存储的结果如下:

GlobalExectionContext = {
  ThisBinding: <Global Object>,
  LexicalEnvironment: {
    EnvironmentRecord: {
      Type: "Object",
      // Identifier bindings go here
      a: < uninitialized >,
      b: < uninitialized >,
      multiply: < func >
    }
    outer: <null>
  },
  VariableEnvironment: {
    EnvironmentRecord: {
      Type: "Object",
      // Identifier bindings go here
      c: undefined,
    }
    outer: <null>
  }
}
FunctionExectionContext = {
 
  ThisBinding: <Global Object>,
  LexicalEnvironment: {
    EnvironmentRecord: {
      Type: "Declarative",
      // Identifier bindings go here
      Arguments: {0: 20, 1: 30, length: 2},
    },
    outer: <GlobalLexicalEnvironment>
  },
VariableEnvironment: {
    EnvironmentRecord: {
      Type: "Declarative",
      // Identifier bindings go here
      g: undefined
    },
    outer: <GlobalLexicalEnvironment>
  }
}

注意:这里的 FunctionExectionContext 只有在 multiple 函数被调用才生成。
可以很明显的看到两者区别:let 和 const 需要初始化,而 var 已经赋了 undefined 的值,其也导致 var 的变量提升。

Execution Phase

执行阶段就是完成所有变量的赋值操作以及最终执行函数。
注意,如果 let 的变量无法再声明时找到赋值,其会被赋 undefined 值。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值