【JavaScript】执行栈和执行上下文

1. 执行上下文(Execution Context)

执行上下文是 JavaScript 中代码执行的环境的抽象概念,它包含了代码运行时所需的所有信息,比如变量的值、函数的引用等。

每当 JavaScript 代码执行前,都会创建一个执行上下文,并将其添加到执行栈中。执行上下文负责代码的执行和管理作用域。

JavaScript 中有三种执行上下文类型(环境)。

  • 全局执行上下文:这是默认或者说基础的上下文,任何不在函数内部的代码都在全局上下文中。他会执行两件事,创建一个全局的 window 对象(浏览器的情况下),并且设置 this 的值等于这个全局对象。
  • 函数执行上下文:每当一个函数被调用时,都会为该函数创建一个新的上下文。每个函数都有它自己的执行上下文,不过是在函数被调用时创建的。函数上下文可以有任意多个。每当一个新的执行上下文被创建,它会按定义的顺序执行一系列步骤。
  • Eval 函数执行上下文:执行在 eval 函数内部的代码也会有它属于自己的执行上下文。

执行上下文包含三个重要的属性:

  • 变量对象(Variable Object):包含变量、函数声明和形参等。
  • 作用域链(Scope Chain):用于解析标识符的链表。
  • this 指向:指向函数执行时的上下文对象。

JavaScript 运行时首先会进入全局环境,对应会生成全局上下文。程序代码中基本都会存在函数,那么调用函数,就会进入函数执行环境,对应就会生成该函数的执行下文。

由于代码中会声明多个函数,对应的函数执行上下文也会存在多个。在JavaScript中,通过栈的存取方式来管理执行上下文,我们可称其为执行栈,或函数调用栈(Call Stack)。

const foo = function (i) {
    console.log(b)  // undefined
    console.log(c)  // [Function: c]
    let a = 'hello'
    let b = function privateB() {}
    function c(){}
}
foo(10)

// 1. 创建上下文阶段

// vo 里面确定的东西:
// 1. 函数的形参(并赋值)
// 2. 函数的 arguments 对象(并赋值)
// 3. 确定普通字面量形式的函数声明(并赋值)
// 3. 变量声明、函数表达式声明(未赋值)

// 将执行上下文看做是一个对象
// fooExecutionContext = {
    // vo = {
    //     i:  10,
    //     arguments: {0: 10, length: 1},
    //     c: 指向 c 那个函数,
    //     a: undefined,
    //     b: undefined
    // },
    // this,
    // scope
// }

// 2. 执行代码阶段
fooExecutionContext = {
    vo = {
        i:  10,
        arguments: {0: 10, length: 1},
        c: 指向 c 那个函数,
        a: 'hello',
        b: privateB
    },
    this,
    scope
}

2. 栈(Stack)

执行栈是一个后进先出(LIFO)的数据结构,用于存储执行上下文。当 JavaScript 代码执行时,会创建执行上下文,并将其推入执行栈的顶部。当函数执行完成后,对应的执行上下文将从栈顶弹出,控制权返回到上一个执行上下文。

执行栈(函数调用栈)

理解完栈的存取方式,我们接着分析 JavaScript 中如何通过栈来管理多个执行上下文。

程序执行会先创建全局执行上下文,所以栈底都是全局执行上下文;而栈顶是正在执行函数的执行上下文。

执行上下文可存在多个,虽然没有明确的数量限制,但如果超出栈分配的空间,会造成堆栈溢出。常见于递归调用,没有终止条件造成死循环的场景。

  • 当脚本要调用一个函数时,解析器把该函数添加到栈中并且执行这个函数。
  • 任何被这个函数调用的函数会进一步添加到调用栈中,并且运行到它们被上个程序调用的位置。
  • 当函数运行结束后,解释器将它从堆栈中取出,并在主代码列表中继续执行代码。
  • 如果栈占用的空间比分配给它的空间还大,那么则会导致“栈溢出”错误。

3. 执行上下文生命周期

执行上下文的生命周期包括以下几个阶段:

  • 创建阶段(Creation Phase):在此阶段,JavaScript 引擎会创建执行上下文。在全局上下文中,这一阶段发生在代码执行前;在函数上下文中,这一阶段发生在函数被调用时。
    • 初始化变量对象(Variable Object / VO)
      • 确定函数形参并赋值
      • 函数环境初始化创建arguments对象并赋值
      • 确定普通字面量形式的函数声明并赋值
      • 变量声明,函数表达式声明(未赋值)
    • 建立作用域链(Scope Chain)(在声明定义的地方确定)
    • 确定 this 的指向(this 由调用者确定)。
  • 执行阶段(Execution Phase):在此阶段,JavaScript 引擎会按照代码的顺序执行相应的代码,并为变量赋值、函数调用等。在执行阶段中,JavaScript 引擎会根据作用域链解析变量和函数标识符,并执行相应的代码逻辑。
  • 销毁阶段(Deletion Phase):在函数执行完成后或全局代码执行完成后,对应的执行上下文会被销毁。JavaScript 引擎会从执行栈中弹出该执行上下文,并释放相关的内存资源。
(function () {
    console.log(typeof foo);
    console.log(typeof bar);
    var foo = "Hello";
    var bar = function A() {
        return "World";
    }

    function foo() {
        return "good";
    }

    console.log(foo, typeof foo);
})()
// 1. 创建上下文阶段
// exeutionContext = {
//     vo: {
//         foo: 指向 foo 函数,
//         // 已有 foo 不会创建 foo 变量了
//         bar: undefined
//     },
//     this,
//     scope
// }
// 2. 执行代码
exeutionContext = {
    vo: {
        foo: "Hello",
        // 已有 foo 不会创建 foo 变量了
        bar: function A
    },
    this,
    scope
}

console.log(typeof foo);  // function
console.log(typeof bar);  // undefined
var foo = "Hello";
var bar = function A() {
    return "World";
}

function foo() {
    return "good";
}

console.log(foo, typeof foo); //hello, string

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/599046.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Echarts柱状图横坐标不显示

本人遇到的问题:折线图横坐标可以正常显示 柱状图接收一样的数据在横坐标却显示不了 1.在前端打印是否能够正常接收数据、数据类型是否有误以及数据是否有内容 console.log(typeof optionbar.xAxis.data)console.log(optionbar.xAxis.data) 2.如上确定能够接收到数…

ue引擎游戏开发笔记(32)——为游戏添加新武器装备

1.需求分析: 游戏中角色不会只有一种武器,不同武器需要不同模型,甚至可能需要角色持握武器的不同位置,因此需要添加专门的武器类,方便武器后续更新,建立一个武器类。 2.操作实现: 1.在ue5中新建…

艺术的新领域——探索元宇宙艺术展带来的沉浸式艺术体验

在数字化的浪潮中,元宇宙艺术展成为了一种全新的展览形式,它通过虚拟现实、3D建模技术和互动平台,将传统艺术与现代科技巧妙结合,提供了一种前所未有的艺术欣赏方式。此类展览不仅展示了艺术作品的新颖呈现,还为参观者…

翻译《The Old New Thing》 - Understanding the consequences of WAIT_ABANDONED

Understanding the consequences of WAIT_ABANDONED - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20050912-14/?p34253 Raymond Chen 2005年09月12日 理解 WAIT_ABANDONED 的后果 简要 文章讨论了在多线程同步中,如果一个线程…

【贪心算法】最小生成树Kruskal算法Python实现

文章目录 [toc]问题描述最小生成树的性质证明 Kruskal算法Python实现时间复杂性 问题描述 设 G ( V , E ) G (V , E) G(V,E)是无向连通带权图, E E E中每条边 ( v , w ) (v , w) (v,w)的权为 c [ v ] [ w ] c[v][w] c[v][w]如果 G G G的一个子图 G ′ G^{} G′是…

中国居民消费新特征:中枢回落,即时满足,去地产化

随着收入预期和财富效应的转变,居民更倾向于通过短期集中式的消费来获得即时满足的快乐,服务消费表现出了更强的韧性。服务消费强于商品消费、消费去地产化、汽车挑大梁的特征延续。 特征一:消费倾向高于2020-22年,低于2017-19年…

AI技术赋能下的视频监控方案是如何解决新能源汽车充电难问题的?

一、方案背景 刚刚结束的第十八届北京车展异常火爆,其中一组与汽车有关的数字让人格外关注。根据乘联会2024年4月19日公布的最新数据,全国乘用车市场零售达到51.6万辆,其中新能源车的销量约为26万辆,市场渗透率达到50.39%。 这意味…

如何让CANoe或Wireshark自动解析应用层协议

当我们使用CANoe软件或Wireshark工具抓取以太网总线上的报文时,网卡首先会把以太网总线上的模拟信号解析成以太网帧数据。数据链路层根据二层头部中的Type字段值确定上层的协议。 如果以太网使用的是TCP/IP协议栈,那么Type值要么是0x0800(IPv4),要么是0x0806(ARP),要么是0x…

SOL链DApp智能合约代币质押挖矿分红系统开发

随着区块链技术的不断发展和普及,越来越多的项目开始探索基于区块链的去中心化应用(DApp)。Solana(SOL)作为一条高性能、低成本的区块链网络,吸引了众多开发者和项目,其中包括了各种类型的DApp&…

Ansible自动化工具模块调用与playbook编写

目录 一、Ansible工作机制与特点 (一)Ansible工作机制 1. 初始化与配置 2. 编写Playbook 3. 调用模块 4. 加密敏感数据 5. 执行Playbook 6. 收集执行结果 7. 错误处理与回滚 8. 反馈与报告 (二)Ansible 的主要特点包括…

信锐交换机简介及应用说明(1)

交换机关键参数及分类 1.线速 线速是指交换机的端口上每秒钟传输的bit数,单位为bps(bit per second,即每秒传输多少bit,一个bit也就是一个二进制数0或者1)。以我们常见的例子来说明的话,比如100M的网卡就…

ComfyUI中图像亮度/对比度/饱和度处理

用上面这个节点可以同时设置图片的亮度、对比度和饱和度。 【保姆级教程】一口气分享在ComfyUI中常用的30多种基本图像处理方式 更多好玩且实用AIGC工作流和节点 星球号:32767063 本期资料链接 往期学习资料 整理AI学习资料库

【容器】k8s获取的节点oom事件并输出到node事件

在debug k8s node不可用过程中,有可能会看到: System OOM encountered, victim process: xx为了搞清楚oom事件是什么,以及如何产生的,我们做了一定探索,并输出了下面的信息。(本文关注oom事件是如何生成&传输的&a…

uniapp的app端软件更新弹框

1:使用html PLUS实现:地址HTML5 API Reference (html5plus.org),效果图 2:在app.vue的onLaunch生命周期中,代码如下: onLaunch: function() {let a 0let view new plus.nativeObj.View(maskView, {backg…

mib browser读取mib文件的oid(飞塔防火墙为例)

在配置zabbix监控的时候,配置监控项最为麻烦,一般我们都会套用模板,这种方式比较简单,但是有些设备就是没有现成的zabbix模板,怎么办? 今天我们使用MIB Browser来获取设备SNMP的OID,然后加入zabbix 。 1.什么是MIB Browser SNMP客户端工具MIB Browser, 全名iReasonin…

#LLM入门 | langchain | RAG # 4.3_文档分割

上一章讨论了文档标准化加载,现在转向文档的细分,这虽简单却对后续工作有重大影响。 一、为什么要进行文档分割 模型大小和内存限制:大型GPT模型参数众多,需大量计算和内存,而硬件设备如GPU或TPU有内存限制&#xff…

Vscode 实现代码跳转功能

随笔 目录 1. 安装Python 2. 安装Pylance 3. 选择解释器 1. 安装Python 2. 安装Pylance 3. 选择解释器 到此即可实现跳转功能

Pytorch学习笔记——神经网络基本框架

一、神经网络是什么 神经网络在人工智能和深度学习的领域,一般称为人工神经网络,即ANN(Artificial Neural Network),是一种模仿人脑神经系统工作方式的计算模型。被广泛应用于人工智能、自动控制、机器人、统计学等领域的信息处理中。 二、…

图像处理之PCA(C++)

图像处理之PCA(C) 文章目录 图像处理之PCA(C)前言一、PCA原理1.原理思想2.实现步骤 二、代码实现总结 前言 在科研、工程应用中,我们往往所获取的数据都包含着很多冗余的信息,这些冗余的信息会对我们分析数…

CP AUTOSAR之CANXLDriver详细说明(正在更新中)

本文遵循autosar标准:R22-11 1 简介及功能概述 本规范描述了AUTOSAR 基础软件模块CAN XL 驱动程序的功能、API和配置。   本文档的基础是[1,CiA610-1]和[2,CiA611-1]。假设读者熟悉这些规范。本文档不会再次描述CAN XL 功能。   CAN XL 驱动程序是最低层的一部…
最新文章