JavaScript执行上下文和调用栈

news/2024/12/3 0:29:46/

上节课我们已经说过了,JavaScript的代码执行是发生在js引擎中的调用堆栈的,但是具体是如何运行的,我们来详细剖析一下

如何执行上下文

执行上下文:
执行上下文是指在JavaScript中代码被执行时所创建的环境。它包含了变量、函数、对象和其他代码执行所需的信息。每当函数被调用时,都会创建一个新的执行上下文。
举个例子:
例如要把装披萨的盒子比作执行上下文,披萨比作JavaScript的代码,但是盒子里面可能并不只有披萨,还有餐具和清单!这样才能构建一个吃披萨(执行代码)的环境!

只有一个全局执行上下文(EC)
默认上下文,为不在任何函数内的代码创建(顶级)。
在这里插入图片描述

顶级代码示例

在这里插入图片描述

声明的变量和声明的函数在全局中使用,所以在顶级代码中就被执行,但是函数内的代码,只有在被调用的时候菜会执行!

执行函数的内部

内部执行上下文

  1. 可变函数
    a. let、const和var声明
    b. 函数
    c. 参数对象

  2. 作用域链
    JavaScript的作用域链是一种用于查找变量和函数的机制。当在代码中引用一个变量时,JavaScript引擎会按照一定的顺序搜索变量的定义。这个搜索过程就是通过作用域链来完成的。
    在JavaScript中,每个函数都有自己的执行上下文,包括一个变量对象(Variable Object),它存储了函数内部定义的变量和函数。当函数被调用时,会创建一个新的执行上下文,并将其添加到作用域链的前端。
    作用域链是一个由多个执行上下文对象组成的链表,它按照函数定义的嵌套关系进行链接。每个执行上下文对象都有一个指向其父级执行上下文对象的引用,这样就形成了一个作用域链。
    当查找一个变量时,JavaScript引擎首先在当前执行上下文的变量对象中查找,如果找到了变量,则使用该变量。如果没有找到,则沿着作用域链向上一级执行上下文的变量对象中查找,直到找到该变量或者到达作用域链的顶端(全局作用域)。
    如果在整个作用域链上都没有找到该变量,则会抛出一个引用错误。
    这种作用域链的机制允许内部函数访问外部函数的变量,即使外部函数已经执行完毕,也仍然可以通过作用域链找到这些变量。这被称为"闭包",是JavaScript中非常强大和有用的特性之一。

  3. this关键字
    "this"关键字在JavaScript中是一个特殊的关键字,它通常用于引用当前执行代码的上下文对象。
    "this"关键字的值在不同的上下文中有不同的含义。它的值取决于函数的调用方式以及函数所属的对象。
    在全局作用域中,"this"引用的是全局对象(在浏览器中是"window"对象,在Node.js中是"global"对象)。
    在函数中,"this"的值取决于函数是如何被调用的。如果函数是作为对象的方法调用的,那么"this"引用的是该对象。如果函数是作为普通函数调用的,那么"this"引用的是全局对象(在浏览器中是"window"对象,在Node.js中是"global"对象)。
    此外,“this"还可以通过一些特殊的函数调用方式来显式地绑定到指定的对象上,例如使用"call”、"apply"或"bind"方法。
    总之,"this"关键字在JavaScript中用于引用当前执行代码的上下文对象,它的值取决于函数的调用方式以及函数所属的对象。

举例说明

在这里插入图片描述

函数调用栈

“位置”执行上下文被堆叠在一起以跟踪我们在执行中的位置。

在这里插入图片描述

示例

const name = 'Jonas';const first = () => {let a = 1;const b = second(7, 9);a = a + b;return a;
};function second(x, y) {var c = 2;return c;
}const x = first();

首先,让我们逐行解释这段代码的执行过程,以了解函数调用栈的原理是如何应用的:

  1. const name = ‘Jonas’; - 这行代码定义了一个常量name并赋值为字符串’Jonas’。这行代码不涉及函数调用,因此不会影响函数调用栈。在全局代码中就会执行!
  2. const first = () => { … } - 这行代码定义了一个箭头函数first。箭头函数不会立即执行,而是在被调用时才执行。因此,此时不会有函数调用栈的变化。
  3. function second(x, y) { … } - 这行代码定义了一个名为second的函数。函数定义本身不会改变函数调用栈,只有在函数被调用时才会推入调用栈。
  4. const x = first(); - 这行代码调用了函数first并将其返回值赋给常量x。函数调用会改变函数调用栈的状态。
    现在我们来分析函数调用栈的变化:
  5. const x = first(); - 这行代码调用了函数first,将其推入函数调用栈的顶部。
  6. const b = second(7, 9); - 在函数first中,调用了函数second,将其推入函数调用栈的顶部。
  7. return c; - 函数second执行完毕,将其执行结果返回给调用者first。
  8. a = a + b; - 在函数first中,将变量b的值加到变量a上。
  9. return a; - 函数first执行完毕,将其执行结果返回给调用者。
  10. const x = first(); - 函数调用栈中只剩下全局上下文,函数调用栈为空。
    最终,常量x的值为3,因为函数first的执行结果是3。
    这个例子展示了函数调用栈的典型行为:当一个函数被调用时,它的执行上下文被推入调用栈的顶部,函数执行完毕后,它的执行上下文从调用栈中弹出,控制权返回给调用者。这个过程会一直重复,直到所有函数执行完毕,调用栈为空。

http://www.ppmy.cn/news/1196656.html

相关文章

上线项目问题——无法加载响应数据

目录 无法加载响应数据解决 无法加载响应数据 上线项目时 改用服务器上的redis和MySQL 出现请求能请求到后端,后端也能正常返回数据,但是在前端页面会显示 以为是跨域问题,但是环境还在本地,排除跨域问题以为是服务器问题&#…

Linux命令(113)之rev

linux命令之rev 1.rev介绍 linux命令rev是将文件中的每行内容已字符为单位反向输出,即第一个字符最后输出,最后一个字符最先输出 2.rev用法 rev [参数] filename rev参数 参数说明-V显示版本信息-h显示帮助信息 3.实例 3.1.显示rev的版本信息 命令…

indexedDB笔记

indexedDB 该部分内容主要源于https://juejin.cn/post/7026900352968425486 常用场景:大量数据需要缓存在本地重要概念 仓库objectStore:类似于数据库中的表,数据存储媒介索引index:索引作为数据的标志量,可根据索引获…

程序员笔记本电脑选 windows 还是 MAC

计算机选择是每个进入 IT 行业同学的第一个重要选择,那么你是怎么选择的呢? 选择操作系统(Windows还是macOS)取决于程序员的需求、偏好和工作流程。每个操作系统都有其优点和缺点,下面将分别讨论它们,以帮助…

Linux 安装 RocketMq

RocketMq是阿里出品(基于MetaQ)的开源中间件,已捐赠给Apache基金会并成为Apache的顶级项目。基于java语言实现,十万级数据吞吐量,ms级处理速度,分布式架构,功能强大,扩展性强。 官网…

【iOS免越狱】利用IOS自动化WebDriverAgent实现自动直播间自动输入

1.目标 由于看直播的时候主播叫我发 666,支持他,我肯定支持他呀,就一直发,可是后来发现太浪费时间了,能不能做一个直播间自动发 666 呢?于是就开始下面的操作。 2.操作环境 iPhone一台 WebDriverAgent …

git clone 报错:fatal: unable to access ‘https://github.com/XXXXXXXXX‘

国内使用GIT工具,拉取github代码,会因为网络原因无法成功拉取。出现如下类似情形: 此时更改 web URL即可,改用镜像的github网站替换https://github.com/。即URL里的https://github.com/换成https://hub.nuaa.cf/,即可…

【华为OD题库-018】AI面板识别-Java

题目 Al识别到面板上有N(1<N≤100)个指示灯&#xff0c;灯大小一样&#xff0c;任意两个之间无重叠。由于AI识别误差&#xff0c;每次识别到的指示灯位置可能有差异&#xff0c;以4个坐标值描述Al识别的指示灯的大小和位置(左上角x1,y1&#xff0c;右下角x2.y2)。请输出先行…