专栏名称: SegmentFault思否
SegmentFault (www.sf.gg)开发者社区,是中国年轻开发者喜爱的极客社区,我们为开发者提供最纯粹的技术交流和分享平台。
目录
相关文章推荐
程序员的那些事  ·  OpenAI ... ·  11 小时前  
OSC开源社区  ·  升级到Svelte ... ·  3 天前  
程序员的那些事  ·  惊!小偷“零元购”后竟向 DeepSeek ... ·  2 天前  
程序员的那些事  ·  成人玩偶 + ... ·  3 天前  
51好读  ›  专栏  ›  SegmentFault思否

深入理解 JavaScript 之执行上下文和执行栈

SegmentFault思否  · 公众号  · 程序员  · 2019-12-02 20:48

正文

本文转载于 SegmentFault 社区
作者:JackySummer



都说想成为出色的 JavaScript 开发者,就要深入学习 JavaScript 程序内部的执行机制,最近学了一遍 JS 的执行上下文和执行栈,以此作总结。


首先先来了解几个专业概念

•  EC:函数执行环境 (或执行上下文) ,Execution Context
ECS:执行环境栈,Execution Context Stack
VO:变量对象,Variable Object
AO:活动对象,Active Object
scope chain:作用域链



什么是执行上下文



每次当控制器转到 ECMAScript 可执行代码的时候,它都是在执行上下文中运行,即是指当前执行环境中的变量、函数声明,参数,作用域链,this 等信息。


组成代码示例


const ExecutionContextObj = {
VO: window, // 变量对象
ScopeChain: {}, // 作用域链
this: window
};




执行上下文的类型



JavaScript 中有三种执行上下文类型。

1. 全局 执行上下文 —— 这是默认上下文,浏览器中的全局对象就是 window 对象,任何不在函数内部的代码都在全局上下文中,this 指向这个全局对象。
2. 函 数执行上下文 —— 当函数被调用时创建,会为该函数创建一个新的执行上下文,可以有任意个。
3. Eva l 函数执行上 下文 —— 执行 eval 函数内部的代码也有属于它的上下文,由于开发中是尽量避免或不用 eval 函数,故此不作讨论。



执行栈



执行栈,也叫调用栈,被用来存储代码运行时创建的所有执行上下文。

栈:一种数据结构,遵循后进先出的原则


当 JavaScript 引擎第一次遇到脚本时,它会创建一个全局的执行上下文并且压入当前执行栈。每当引擎遇到一个函数调用,它会为该函数创建一个新的执行上下文并压入栈的顶部。

引擎会执行那些执行上下文位于栈顶的函数。当该函数执行结束时,执行上下文从栈中弹出,控制流程到达当前栈中的下一个上下文。

function fn1() {
console.log('fn1被调用了 -- 创建了fn1的函数执行上下文,压入栈');
fn2();
console.log('fn2执行完成,fn2的执行上下文会从栈中弹出');
}

function fn2() {
console.log('fn2被调用了 -- 创建了fn2的函数执行上下文,压入栈');
}

fn1();
console.log('fn1执行完成,fn2的执行上下文会从栈中弹出');

运行结果:

fn1被调用了 -- 创建了fn1的函数执行上下文,压入栈
fn2被调用了 -- 创建了fn2的函数执行上下文,压入栈
fn2执行完成,fn2的执行上下文会从栈中弹出
fn1执行完成,fn2的执行上下文会从栈中弹出

上述代码的执行上下文栈:


当上述代码在浏览器加载时,JavaScript 引擎创建了一个全局执行上下文并把它亚压入栈中,当函数 fn1() 被调用时,JavaScript 为该函数创建了一个函数执行上下文,并把它压入当前执行栈的顶部。

当 fn1() 函数内部调用 fn2() 函数时,JavaScript 引擎同样创建了 fn2() 的函数执行上下文并压入栈的顶部。然后执行了 fn2() 函数后,fn2() 函数会从当前栈 (后进先出结构) 弹出,并且按程序执行顺序继续执行 fn1() 函数,即此刻处于 fn1 的函数执行上下文。

当 fn1() 函数执行完毕,它的执行上下文从栈弹出,控制流程到达全局执行上下文。一旦所有代码执行完毕,JavaScript 引擎从当前栈中移除全局执行上下文。



执行上下文的创建



已经知道 JavaScript 怎样管理执行上下文了,现在来了解 JavaScript 引擎是怎么创建执行上下文的。


创建执行上下文有两个阶段:

1. 创建阶段
2. 执行阶段。

在 JavaScript 代码执行前,执行上下文将经历创建阶段。 在创建阶段会发生三件事:

1. this 绑定
2. 创建 (LexicalEnvironment) 词法环境组件
3. 创建 (VariableEnvironment) 变量环境组件

执行上下文在概念可表示为:

ExecutionContext = {
ThisBinding = ,
LexicalEnvironment = { ... },
VariableEnvironment = { ... },
}

(一)创建阶段


this 绑定


在全局执行上下文中,this 的值指向全局对象。 (在浏览器中,this 引用 window 对象)

在函数执行上下文中,this 的指向取决于函数是如何被调用的,在本篇暂不对 this 指向做详细讨论。


let






请到「今天看啥」查看全文