执行上下文和调用堆栈

执行上下文和调用堆栈

为顶级代码创建全局执行上下文,即不在任何 fn 内的代码。因此,首先执行 fn 之外的代码。
fn-decln/exprsn 的 fn 主体内的代码仅在调用时执行。

执行上下文(ec)

一段js执行的环境。
存储一些要执行的代码的所有必要信息,例如局部变量、传递给 fn 的 args。
js 代码始终在 ec 内运行。
无论 js 项目有多大,都只有一个全局 ec。
默认上下文,为不在任何 fn 内的代码创建。
然后代码在全局ec内部执行
顶层代码执行完毕后,执行fns并等待c/bs
对于每个 fn 调用,都会创建一个新的 ec 来执行该 fn。方法也是如此,因为它们也是附加到对象的 fns。
所有这些 ec 共同构成了调用堆栈。
当所有 fns 执行完毕后,引擎等待 cb 到达并执行它们。前任。点击事件回调,由事件循环提供。

ec里面有什么

变量环境由组成let、const、var 声明功能

arguments 对象:将传递给 fn 的所有参数存储在其 ec 中。
每个 fn 都有自己的 ec 作为其名称。声明的变量最终位于变量环境中

范围链:
fns 可以使用作用域链访问 fns 之外的变量。
包含对当前 fn 外部变量的引用并跟踪作用域链,它存储在每个 ec 中。

每个 ec 还获得 ‘this’ 关键字。

以上三个都是在执行之前的“创建阶段”生成的。这些是在顶层运行代码所必需的。

对于箭头 fns ec:

我们不会有:arguments 对象、this 关键字。箭头 fn 使用最接近的常规 fn,即上述两个。

参数:类数组对象,包含传递到常规 fn 的所有参数,而不是箭头 fn。

调用栈+内存堆=js引擎

调用栈

ec 相互堆叠的地方,以跟踪我们在执行中的位置。最顶层的 ec 是我们正在运行的 ec。当执行结束时,它会从栈顶移除,控制权会转移到底层 ec。
如果存在嵌套的 fn 调用,由于 js 只有一个执行线程,因此会暂停外层 fn 调用,以便在调用堆栈上返回内层 fn 的执行结果。现在上一个 ec 将成为活动 ec
然后最顶层的 ec 在返回时从调用堆栈中弹出。
调用堆栈中最低的将是全局 ec,最上面的将是按顺序发生的 fn 调用。
确保执行顺序永远不会丢失。
最终程序完成,全局ec也会从call stack中弹出。

js 代码在 ec 内部运行,ec 放置在 call stack 上。

hence, we can say that each ec has:1. variable environment2. scope chain3. 'this' keyword

范围界定

js 引擎如何组织和访问我们的程序变量。
变量存在于哪里
我们在哪里可以访问某些变量,哪里不能。

词汇范围:

js 具有 leical 作用域,这意味着作用域是通过代码中 fns 和块的放置来控制的。
前任。嵌套的 fn 可以访问其父 fn 的变量。

范围:

声明某个变量的空间或环境(fns 中的变量环境)。它是存储在 fns ec 中的变量 env。
对于 fns,var env 和scope 都是相同的。

three scopes in js are:1. global scope2. fn scope3. block scope [es6]

作用域是声明变量的地方。因此,对于 fns 来说也是如此,因为 fns 只是存储在变量中的值。

变量的范围

可以访问某个变量的代码区域。

作用域与变量的作用域有细微的差别。

## global scope:for top level codefor variables declared outside of any fn or block which are accessible from everywherevariables in this scope are at the top of scope chain. hence, can be used by every nested scope.
## fn scope:each fn has creates its own scopevariables are accessible only inside fn, not outside. else reference erroralso called local scopefn decln, exprsn, arrow all three create their own scopes.only way to create scope using es5 which had only fn & global scope.
## block scope:introduced in es6, not only fn but {} also create a scope known as block scope which work only for es6 variables i.e let-const types. doesn't work for variables declared with 'var' as its fn scoped.variables accessible only inside block i.e {} this only applies to variables declared with let-const only.fns are also block scoped in es6 (only in strict mode, should be used)variables declared using 'var' will be accessible outside the blockscoped to the current fn or the global scope.var variables only care about fn, they ignore blocks. they end up in nearest fn scope.

每个嵌套作用域都可以访问其外部作用域和全局作用域中的变量。同样也适用于 fn 参数。

如果 fn 在其作用域中找不到该变量,它将查找作用域链以找出其外部作用域中的变量。这个过程称为作用域链中的变量查找。反之则不行,即我们无法从 fn 或外部作用域之外访问嵌套的 fn 变量或作用域。
兄弟作用域无法访问彼此的变量
只有最内层的作用域可以访问其外层的作用域,反之则不然。

每个 fn 都有一个 ec,按照调用 fn 的确切顺序放置在调用堆栈上,其变量位于 ec 内。 global ec 位于调用堆栈的底部

范围链:
这完全取决于代码中 fns 的编写顺序。
与调用 fns 的顺序无关。
作用域链从 ec 获取变量环境。
fn 调用的顺序与作用域链完全无关。

const a = 'Alice';first();function first(){  const b = "Hello";  second();  function second(){    const c = "Hi";    third();  }}function third(){  const d = "Hey";  console.log(d + c + b + a); // Reference Error}## Call Stack order:third() EC - topsecond() ECfirst() ECglobal EC - bottomScope Chain:second() --nested inside--> first() --nested inside--> global scope.third() is independently defined inside gloabal scope.Reference Error occurred because both 'c' as well as 'b' cannot be accessed using the scope chain.

摘要:
e-c、var env、cl-sk、scope、scope-chain 都是不同但相关的概念。
范围界定询问变量存在于哪里、我们可以在哪里访问变量、在哪里不能访问变量等问题。
js 中的词法作用域:我们可以访问变量的规则完全基于代码中 fns 和块的写入位置。
每个作用域都可以访问其所有外部作用域的所有变量。这是范围链,是一条单向街道。外部作用域永远无法访问内部作用域的变量。
某个作用域的作用域链等于将所有父作用域的所有 var env 加在一起。
作用域链与 fns 的调用顺序无关。它根本不影响作用域链。
当在当前作用域中找不到变量时,引擎会查找作用域链,直到找到所需的变量。这称为变量查找。

以上就是执行上下文和调用堆栈的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1491592.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
搜索和(法学硕士)转换
上一篇 2025年12月19日 14:05:56
掌握 JavaScript 比较:从基础到高级
下一篇 2025年12月19日 14:06:10

相关推荐

  • php常量怎么用_PHP常量(define/const)定义与使用方法

    PHP中可通过define函数和const关键字定义常量,用于存储不可变值。define适用于全局作用域,支持动态名称和条件定义,如define(‘SITE_NAME’, ‘MyWebsite’);const在编译时生效,语法简洁但限制多,只能在类或全…

    2026年5月10日
    000
  • JavaScript 闭包:理解闭包原理与内存泄漏问题

    闭包是函数访问其外部作用域变量的能力,即使外部函数已执行完毕。如 inner 函数引用 outer 中的 count,形成闭包,使变量持久存在。闭包本身无害,但可能因延长变量生命周期导致内存泄漏,例如事件监听器引用大对象时。若未及时清理 DOM 事件或定时器,闭包会阻止垃圾回收,造成内存占用过高。解…

    2026年5月10日
    100
  • JavaScript 动态菜单点击高亮效果实现教程

    本教程详细介绍了如何使用 JavaScript 实现动态菜单的点击高亮功能。通过事件委托和状态管理,当用户点击菜单项时,被点击项会高亮显示(绿色),同时其他菜单项恢复默认样式(白色)。这种方法避免了不必要的DOM操作,提高了性能和代码可维护性,确保了无论点击方向如何,功能都能稳定运行。 动态菜单高亮…

    2026年5月10日
    200
  • PHP多维数组到复杂XML结构的SOAP序列化实践

    本文旨在解决php多维数组向复杂soap xml结构序列化时遇到的“无法序列化结果”问题。通过深入理解soap xml的结构要求,包括命名空间和类型属性,文章将指导您如何构建符合特定xml schema的php关联数组。我们将利用`spatie/array-to-xml`库,详细演示其安装与使用方法…

    2026年5月10日
    100
  • JavaScript 高效判断页面所有复选框状态的技巧与实践

    本文旨在提供一套高效且专业的javascript方法,用于判断网页中所有复选框的选中状态。我们将探讨如何利用`array.some()`快速确定是否有未选中的复选框(进而判断是否全部选中),以及如何使用`array.filter()`统计选中和未选中的复选框数量。通过优化dom元素选择和数组操作,提…

    2026年5月10日
    100
  • CodeIgniter在IIS环境下实现URL重写与index.php移除指南

    本教程详细指导如何在IIS服务器上部署的CodeIgniter应用中,移除URL中不必要的index.php。核心解决方案涉及修改CodeIgniter的config.php文件,将$config[‘index_page’]设置为空,并辅以正确的IIS web.config重…

    2026年5月10日
    100
  • c++中头文件和源文件的区别_c++头文件与源文件作用对比

    头文件声明接口,源文件实现逻辑。头文件含类、函数声明及宏定义,通过#include被多文件共享,用include守卫防重;源文件实现具体功能,编译为目标文件后由链接器合并。声明与实现分离提升模块化与编译效率,模板和内联函数因需编译时可见故常置于头文件,命名空间避免符号冲突,整体结构使项目更清晰易维护…

    2026年5月10日
    000
  • p5.js图像像素化与阈值处理:loadPixels()函数深度解析与性能优化

    本教程深入探讨p5.js中`loadpixels()`函数在图像像素化与阈值处理中的应用。我们将重点讲解如何优化`loadpixels()`的调用时机以提升性能,正确计算图像亮度,并构建清晰有效的条件阈值逻辑。文章还涵盖了避免变量命名冲突、选择合适的绘图函数等关键实践,旨在帮助开发者高效、准确地实现…

    2026年5月10日
    000
  • Bootstrap和MDB固定导航栏遮挡内容:如何优雅地解决页面跳转后内容被遮挡的问题?

    解决bootstrap和mdb固定导航栏遮挡内容的问题 使用Bootstrap和MDB框架构建网站时,固定导航栏遮挡内容是一个常见问题。尤其在页面跳转后,目标内容区域会被导航栏遮挡。本文提供一种优雅的解决方案,无需修改HTML结构,即可在页面跳转后自动调整滚动位置,避免内容被遮挡。 问题:点击导航链…

    2026年5月10日
    000
  • 从指定ID开始输出DOM元素列表

    本文旨在提供一个JavaScript教程,指导开发者如何从用户指定的ID元素开始,输出DOM元素列表。通过修改现有的DOM树遍历函数,并结合用户输入,我们可以动态地展示DOM树的特定部分。本文将详细解释如何获取用户输入、定位起始元素,以及构建和显示DOM元素列表。 实现原理 核心思路在于修改原有的 …

    2026年5月10日
    100
  • WebAssembly中导入JavaScript函数:无胶水代码集成指南

    本文深入探讨了在WebAssembly模块中直接导入和使用JavaScript函数的机制,特别是当使用Emscripten的STANDALONE_WASM和SIDE_MODULE编译模式时。文章详细分析了TypeError: import object field ‘GOT.mem&#8…

    2026年5月10日
    000
  • JavaScript设计原则_JavaScript可维护代码

    每个函数应只做一件事,如拆分数据处理与DOM操作,命名体现功能(如formatDate),长度控制在20行内;2. 使用清晰命名(如currentUser、isValid)减少注释依赖,关键逻辑注明“为什么”;3. 按功能模块化组织代码,如api.js处理请求,utils.js存放工具函数,使用im…

    2026年5月10日
    000
  • 解决React中按钮点击不显示弹出表单的问题:状态管理与语法修正

    本教程旨在解决react应用中点击按钮后弹出表单未能正确渲染的问题。核心在于识别并修正代码中的语法错误以及未定义的react状态管理函数。我们将详细探讨如何使用`usestate`等react hooks来声明和管理组件状态,确保交互逻辑的正确实现,并提供结构清晰的代码示例,帮助开发者构建功能完善的…

    2026年5月10日
    000
  • PHP代码注入检测日志分析_PHP代码注入日志检测方法详解

    答案:日志分析是发现PHP代码注入的关键手段,主要通过Web服务器访问日志、PHP错误日志、PHP-FPM日志及应用自定义日志等多源数据,结合grep、ELK、WAF等工具识别含eval()、system()、Base64编码、目录遍历等特征的异常请求,并建立基线、设置检测规则与自动化告警,配合事件…

    2026年5月10日
    000
  • 使用 JavaScript 将变量值显示在 <h1> 标签中

    本文旨在解决 JavaScript 中无法将变量值正确显示在 标签中的问题。我们将通过分析常见错误原因,提供清晰的代码示例,并介绍最佳实践,帮助开发者正确地使用 JavaScript 操作 DOM 元素,实现动态更新 标签内容的功能。 在 Web 开发中,经常需要使用 JavaScript 动态地更…

    2026年5月10日
    000
  • Go语言与Microsoft SharePoint集成指南

    Go语言可以有效集成Microsoft SharePoint,主要通过两种途径:一是利用SharePoint提供的RESTful API进行数据交互,Go的标准HTTP客户端库即可轻松实现;二是通过SharePoint应用模型开发自托管应用,这种模型支持使用包括Go在内的任何语言编写后端逻辑。 1.…

    2026年5月10日
    000
  • Python继承中父类属性的初始化与访问策略

    本文深入探讨python面向对象编程中,子类如何正确初始化和访问父类属性。重点分析`super().__init__()`的工作原理,解释在继承链中参数传递的重要性,并提供通过子类构造函数传递参数的解决方案。此外,针对子类需要与特定父类实例交互的场景,文章还介绍了组合(composition)模式的…

    2026年5月10日
    000
  • 如何用Golang构建无状态微服务 分享Session管理最佳实践

    如何用Golang构建无状态微服务 分享Session管理最佳实践如何用Golang构建无状态微服务 分享Session管理最佳实践如何用Golang构建无状态微服务 分享Session管理最佳实践如何用Golang构建无状态微服务 分享Session管理最佳实践

    构建无状态微服务时,session管理可通过jwt、redis和统一认证中心实现。①使用jwt作为token,客户端存储,服务端无状态;②结合redis记录session元数据,支持主动失效;③设立统一认证中心,中间件校验token;④确保https传输安全并设计token刷新机制。 用 Golan…

    2026年5月10日 用户投稿
    000
  • 解决PHP foreach循环中变量“继承”问题:理解与避免意外数据泄露

    本文探讨PHP foreach循环中一个常见的陷阱:当循环内部的数组或变量未被显式初始化时,其值可能会“继承”自上一次循环迭代,导致意外的数据泄露和逻辑错误。文章将深入分析这一现象的根源,并通过示例代码展示如何通过在每次迭代开始时正确初始化变量来解决此问题,确保代码行为的预期一致性。 引言:fore…

    2026年5月10日
    100
  • c++如何实现函数的重载_c++函数重载实现方法

    函数重载通过参数列表差异实现,如类型、数量或顺序不同,编译器根据实参选择对应函数,返回类型不同不能单独用于重载。 在C++中,函数重载允许在同一作用域内定义多个同名函数,只要它们的参数列表不同(参数个数、类型或顺序不同),编译器会根据调用时传入的实参来选择匹配的函数。函数重载不能仅通过返回类型的不同…

    2026年5月10日
    000

发表回复

登录后才能评论
关注微信