JavaScript 执行上下文

news2024/11/19 9:38:16

什么是执行上下文

JavaScript是一种客户端脚本语言,通常在Web浏览器中执行。当您在浏览器中加载网页时,浏览器会解析HTML文档并创建文档对象模型 (DOM)。在这个过程中,浏览器会寻找包含JavaScript代码的script标签并执行这些代码。

当浏览器执行JavaScript代码时,会将代码提交给JavaScript引擎进行解析。引擎会将代码转化为由许多小步骤组成的一个指令序列,然后依次执行这些步骤。这个过程被称为执行上下文(execution context)。

执行上下文(Execution context)是 JavaScript 引擎在执行代码时的内部概念,用于描述当前代码的运行环境。执行上下文包含了当前代码的变量、函数和对象的作用域,以及 this 的值。每当 JavaScript 引擎开始执行一段代码时,就会创建一个新的执行上下文,并将其压入执行栈(Execution stack)中。

执行上下文的类型

JavaScript 有三种执行上下文:全局执行上下文(Global execution context)和函数执行上下文(Function execution context),Eval函数执行上下文三种类型。

全局执行上下文是 JavaScript 程序开始运行时创建的第一个执行上下文,它代表全局作用域,即在任何函数外部定义的变量都是全局变量。在全局执行上下文中,this 的值是 window 对象。

函数执行上下文是在调用函数时创建的执行上下文,它代表函数的作用域。在函数执行上下文中,this 的值取决于函数的调用方式。

在js代码中,一个程序是由多个代码片段组成的,有些代码片段会有自己独特的功能和处理逻辑以及独立的运行环境,在函数执行时,js引擎为每一个被调用的函数创建的一个新的代码运行环境(即新的执行上下文),对于一段js脚本来说,它可能会有很多个函数,并且互相之间是互相嵌套的,那他们的执行顺序会像套娃一样一层套一层,执行时也会遵循LIFO(后进先出)的机制进行执行,这种数据结构的栈被称为执行栈,也就是控制代码执行顺序的地方。
在这里插入图片描述

执行栈(Execution stack)是 JavaScript 引擎用于维护当前执行的代码的一种数据结构。当 JavaScript 引擎开始执行一段代码时,会创建一个新的执行上下文并将其压入执行栈顶部。当前正在执行的代码始终位于栈顶,执行完毕后会弹出栈顶的执行上下文。

创建执行上下文的过程叫做执行上下文的入栈(Push)。当 JavaScript 引擎遇到 return 语句或者执行完毕时,会执行执行上下文的出栈(Pop)操作,即将当前执行上下文从执行栈中弹出。

下面是一个示例,展示了在全局执行上下文和函数执行上下文之间切换时执行栈的变化:

function foo() {
  console.log('foo');
}

function bar() {
  foo();
  console.log('bar');
}

console.log('global');
bar();

在执行上述代码时,JavaScript 引擎会创建三个执行上下文,分别对应全局作用域、函数 foo 的作用域和函数 bar 的作用域。执行栈的变化如下:

  1. 创建全局执行上下文并入栈。执行 console.log(‘global’)。
  2. 创建函数 bar 的执行上下文并入栈。
  3. 创建函数 foo 的执行上下文并入栈。执行 console.log(‘foo’)。函数 foo 的执行上下文出栈。
  4. 执行 console.log(‘bar’)。函数 bar 的执行上下文出栈。

注意,JavaScript 是单线程的,所以执行栈中只会存在一个执行上下文。同一时刻,只有栈顶的执行上下文会被执行,其余的执行上下文都会被暂停。

Eval函数执行上下文,一种特殊的函数执行上下文,但有区别与函数执行上下文,在js中eval()函数会将传入的字符串当作js代码执行,因此js引擎也就会为其创建独立的运行环境。

执行上下文生命周期

执行上下文的生命周期指的是从创建执行上下文到销毁执行上下文的过程。执行上下文的生命周期可以分为三个阶段:创建、执行和销毁。

  • 创建阶段

在创建阶段,执行上下文被创建并初始化。 创建阶段是在代码即将运行之前,也就是代码被解析之前的过程,主要任务包括确定 this 的值(this 绑定)、创建词法环境和创建变量环境(设置作用域链)。

在全局执行上下文中,this 指向全局对象(如浏览器中的 window 对象)。在函数执行上下文中,this 的值取决于函数的调用方式,可以是默认绑定、隐式绑定、显式绑定、new 绑定或箭头函数绑定。

词法环境是一种根据 ECMAScript 代码的词法嵌套结构来定义标识符和具体变量和函数的关联的规范类型。它由环境记录器和一个可能的外部词法环境的引用组成。环境记录器存储了当前环境中的变量和函数声明的实际位置,而对外部环境的引用则允许访问其外部词法环境。词法环境有两种类型:全局环境和函数环境。全局环境是没有外部变量环境是一种规范类型,用于描述变量的作用域链。它由一个环境记录器和可能的外部变量环境的引用组成。环境记录器存储了当前环境中的变量声明的实际位置,而对外部环境的引用则允许访问其外部变量环境。

变量环境与词法环境之间的关系是,变量环境是通过词法环境来实现的。每个执行上下文都有一个词法环境和一个变量环境。在创建阶段,词法环境被创建并将其赋值给执行上下文的 LexicalEnvironment 属性,变量环境被创建并将其赋值给执行上下文的 VariableEnvironment 属性。

  • 执行阶段

执行阶段是指在代码已经解析完成并准备运行时的过程 。 在执行阶段,执行上下文会根据词法环境和变量环境来执行代码,执行上下文会维护执行过程中的状态,例如变量的值和执行的位置。

在执行阶段,当执行到一个声明语句(如变量声明或函数声明)时,会将声明的标识符添加到变量环境中。当执行到一个表达式(如赋值操作或函数调用)时,会在变量环境中查找标识符的值。如果找不到,会继续在外部变量环境中查找,直到找到为止,或者如果找不到就会抛出一个 ReferenceError 错误。

执行阶段的主要过程如下:

  1. 从执行栈的顶部开始执行代码。
  2. 在执行过程中,当遇到一个函数调用时,会创建一个新的执行上下文并将其加入执行栈的顶部。
  3. 在执行过程中,当遇到一个 return 语句时,会终止当前执行上下文并从执行栈中弹出。
  4. 在执行过程中,当执行栈为空时,代码执行完毕。
  • 销毁阶段

在销毁阶段,执行上下文被销毁。这包括清除执行上下文中的信息,并释放相关的资源。

执行上下文的生命周期是动态的,并且取决于代码的执行情况。例如,如果代码中有一个函数调用,那么会创建一个新的执行上下文来执行函数体,并在函数执行完后销毁这个执行上下文。

在 JavaScript 中,执行上下文是动态的,并且在代码执行过程中不断地创建和销毁。以下是一个简单的示例,展示了如何创建、执行和销毁执行上下文:

function greet(name) {
  console.log(`Hello, ${name}!`);
}

greet('John'); // 创建执行上下文,执行函数体,销毁执行上下文

在这个示例中,当函数 greet 被调用时,会创建一个新的执行上下文来执行函数体。执行上下文会维护函数的参数和局部变量,并在函数执行完后销毁。

执行上下文还可以嵌套,例如:

function outer() {
  function inner() {
    console.log('I am inside!');
  }

  inner(); // 创建执行上下文,执行函数体,销毁执行上下文
}

outer(); // 创建执行上下文,执行函数体,销毁执行上下文

在这个示例中,当函数 outer 被调用时,会创建一个新的执行上下文来执行函数体。当函数 inner 被调用时,又会创建一个新的执行上下文来执行函数体。最后,这两个执行上下文都会在执行完后销毁。

变量对象 作用域

执行上下文的另一个重要概念是变量对象(Variable object)。变量对象是执行上下文中存储变量和函数声明的对象。在全局执行上下文中,变量对象是 window 对象;在函数执行上下文中,变量对象是 arguments 对象。

变量对象有一个属性叫做作用域链(Scope chain),用于描述执行上下文中可访问的变量和函数。 作用域是指在代码中变量和函数可以被访问的范围。在 ECMAScript 中,作用域是以词法方式实现的,也就是说,在代码中写的位置就决定了变量和函数的作用域。 作用域链是一个从内到外的双向链表,其中第一个节点是变量对象本身,每个后继节点都是一个对象。在全局执行上下文中,作用域链只包含一个节点,即变量对象本身;在函数执行上下文中,作用域链包含变量对象和它的所有父级函数的变量对象。

ECMAScript 中有两种作用域:全局作用域和局部作用域。全局作用域是最外层的作用域,它包含了整个代码。局部作用域是在函数内部创建的作用域,它只包含了函数内部的代码。

在 ECMAScript 中,变量的作用域是在它被声明的地方确定的。如果一个变量在全局作用域中被声明,那么它就是全局变量,可以在整个代码中访问。如果一个变量在函数作用域中被声明,那么它就是局部变量,只能在函数内部访问。

函数的作用域也是在它被声明的地方确定的。如果一个函数在全局作用域中被声明,那么它就是全局函数,可以在整个代码中访问。如果一个函数在函数作用域中被声明,那么它就是局部函数,只能在函数内部访问。

在 ECMAScript 中,作用域链是一个由作用域组成的链表,用于查找变量和函数的值。当查找一个标识符的值时,会按照从内到外的顺序查找作用域链中的每一个作用域。如果在作用域链中找到了标识符,则返回其值;如果没有找到,则抛出一个 ReferenceError 错误。

在全局执行上下文中,作用域链只包含一个作用域,即全局作用域。在函数执行上下文中,作用域链包含多个作用域。首先是函数作用域,然后是包含函数的作用域,以此类推直到全局作用域。

下面是一个示例,展示了在全局执行上下文和函数执行上下文中的变量对象和作用域链的变化:

var x = 1;

function foo() {
  var y = 2;
  console.log(x); // 1
  console.log(y); // 2
}

foo();

在执行上述代码时,JavaScript 引擎会创建两个执行上下文,分别对应全局作用域和函数 foo 的作用域。

在全局执行上下文中,变量对象是 window 对象,作用域链只包含 window 对象本身。所以在全局执行上下文中,可以访问全局变量 x。

在函数 foo 的执行上下文中,变量对象是 arguments 对象,作用域链包含 arguments 对象和 window 对象。所以在函数 foo 的执行上下文中,可以访问局部变量 y 和全局变量 x。

另外,JavaScript 还有一种特殊的执行上下文——严格模式执行上下文(Strict mode execution context)。严格模式下,JavaScript 引擎会对代码进行更严格的检查,并会改变 this 的默认值。可以在函数或者全局作用域中使用 “use strict” 指令启用严格模式。

例如,在严格模式下,this 的默认值为 undefined,而不是非严格模式下的 window 对象。

下面是一个示例,展示了在严格模式和非严格模式下 this 的取值:

function foo() {
  console.log(this);
}

foo(); // window (非严格模式) / undefined (严格模式)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

46.Isaac教程--在机器人应用Deepstream

在机器人应用Deepstream ISAAC教程合集地址: https://blog.csdn.net/kunhe0512/category_12163211.html 文章目录在机器人应用Deepstream技术组件工具技术 NVIDIA DeepStream SDK 为基于 AI 的视频和图像感知以及多传感器处理提供了完整的流分析工具包。 DeepStream 是 NVIDIA…

NUXT学习笔记【part1】nuxt的安装、自定义布局、路由跳转

一、NUXT概述 NUXT 是一个基于 Vue.js 的轻量级应用框架,可用来创建服务端渲染 (SSR) 应用,也可充当静态站点引擎生成静态站点应用,具有优雅的代码结构分层和热加载等特性。NUXT使用服务端渲染技术,可以获得更快的内容到达时间&a…

markdown 写微信公众号,排版交给 mdnice

mdnice 墨滴软件( https://product.mdnice.com/ ),提供了以面向微信公众号内容排版为主的辅助工具 Markdown Nice[1],效果堪称完美,极大的提升了发布微信公众号文章的效率。 使用其在线编辑器( https://e…

L4 Latent Variable Model

Lecture4 Latent Variable Model 在之前我们所介绍的Autoregressive Model和Flow Model中,讨论的都是observable的数据,及一切数据都是可以观测到的。这一讲主要讨论的是latent variable model,即有些变量我们是无法直接观测的。 Latent Va…

2022尚硅谷SSM框架跟学(六)Spring MVC基础一

2022尚硅谷SSM框架跟学 六Spring MVC基础一三、SpringMVC1.SpringMVC简介1.1什么是MVC1.2什么是SpringMVC1.3SpringMVC的特点2入门案例2.1开发环境2.2创建maven工程(1)添加web模块(2)打包方式:war(3)引入依赖2.3配置web.xml(1)默认配置方式(2)扩展配置方式2.4创建请…

C++封装Halcon算法动态链接库Dll补充

前面写了一篇关于C封装DLL的文章,这里是做一个补充。 一、关于如何配置halcon和opencv库不再多说,前面文章介绍的很详细。下面介绍封装新增的东西。 1.1 首先创建类function1,并编写function.h和function1.cpp代码。 function1.h代码 #pra…

处理任务失败附实验(RH294)

首先,一个任务执行失败是肯定会遇见的事情而这时候,就需要一个备用的计划忽略任务失败默认情况下 任务失败的时候play会终止但是,我们可以通过忽略失败的任务来覆盖此行文使用关键字 ignore_errors举个栗子- name: Latest version of notapkg…

《流浪地球 2》 Deepfake 小试牛刀,45+ 吴京「被」年轻,变身 21 岁小鲜肉

内容一览:在春节档科幻电影「流浪地球 2」中,主演吴京、刘德华、沙溢等人饰演的角色,跨越 14 年之久,视效团队正是借助 Deepfake de-aging 技术,呈现出了演员不同年龄段的容貌。 关键词:De-aging Deepfa…

回收租赁商城系统功能拆解13讲-分销会员

回收租赁系统适用于物品回收、物品租赁、二手买卖交易等三大场景。 可以快速帮助企业搭建类似闲鱼回收/爱回收/爱租机/人人租等回收租赁商城。 回收租赁系统支持智能评估回收价格,后台调整最终回收价,用户同意回收后系统即刻放款,用户微信零…

springboot应用项目的打包和部署

jar包方式打包部署 springboot项目在为进行打包处理时就已经可以进行运行调试,是因为springboot项目内嵌了Tomcat服务器. .1添加Maven打包插件。在对Spring Boot项目进行打包(包括ar包和War包)前,需要在项目pom.xml文件中加入Maven打包插件&#xff0c…

倾角传感器的六大应用场合

倾角传感器又名水平传感器、水平仪、倾角仪,是角度传感器的一种,是运用惯性原理的一种加速度传感器,可以通过检测使用环境中的倾斜角度判断设备的倾斜状态,并在监测物出现角度偏差时,倾角传感器能够将异常数据传达给管…

【自学Docker 】Docker export命令

Docker export命令 概述 docker export教程 docker export 命令可以用于将 Docker容器 里的文件系统作为一个 tar 归档文件导出到标准输出。docker export 命令后面的 CONTAINER 可以是容器Id,或者是容器名。 docker save 命令用于将 Docker 镜像保存成 tar 包&a…

5nm三苯甲基/P3HT-PY/CdSe油溶性碳量子点CdSe/ZnS-PrPC的制备方法

5nm三苯甲基/P3HT-PY/CdSe油溶性碳量子点CdSe/ZnS-PrPC的制备方法今天小编分享制备三苯甲基功能化油溶性碳量子点的制备过程,一起看看吧:三苯甲基功能化油溶性碳量子点的制备过程:将50 mg Amino-CQDs放置在100 mL圆底烧瓶中,加入 50 mL二氯甲…

PyQt6-QLabel学习笔记

QLabel支持文本或图片显示,是任何GUI设计中最常用的控件之一。一、QLabel基本概述QLabel标签用于显示,可以以多种方式进行外观配置,没有提供用户交互功能,但是可以用于为另一个小部件指定焦点助记符或快捷键。显示内容类型类型说明…

HoloLens 2 应用开发流程笔记

本文链接:微信推文阅读效果更佳 目录安装工具应用开发举例配置 Unity创建新的 Unity 项目切换生成平台导入和配置资源导入 MRTK Unity 基础包配置 Unity 项目为 XR SDK 配置项目设置创建场景并配置 MRTK交互例子添加并调整第一个立方体向立方体添加脚本添加第二个立…

20篇高质量程序人生文章分享,做开发不仅仅只有代码

我一直觉得,我们做开发,不应该只有代码,合上公司的电脑脱离了公司的产品需求就脱离了程序,而应该结合软件的程序思维去更多的思考我们所处的生活和空间,从而指导自己面对更多的未曾见过的人与事,这可能就是…

Java基础之异常处理

一、小试牛刀 num1 / num2 当除数为零时,程序就会抛出异常,程序就会崩溃而导致退出。 我们可以通过异常处理机制来解决该问题 如果我们认为一段代码可能发生异常,可以使用try-catch-finally异常处理机制来解决。从而保证程序的健壮性。 将可能…

前端工程化-多维度检测重复代码

更多文章可关注我的个人博客:https://seven777777.github.io/myblog/ 1. 检测项目重复代码 1.1 检测方案:jscpd 方法一: 全局安装jscpd依赖npm i -g jscpd项目根路径执行:jscpd -p "src/**/*.js" -k 15 -l 5 方法二…

【黑马SpringCloud(3)】Docker

Docker初识DockerDocker与虚拟机的区别Docker架构DockerHubDocker镜像操作Docker容器操作数据卷自定义镜像镜像结构Dockerfile构建Java项目基于java:8-alpine镜像,构建java项目集群部署微服务Docker-Compose镜像仓库搭建私有镜像仓库Docker安装:https://…

Go第 14 章 :文件操作

Go第 14 章 :文件操作 14.1 文件的基本介绍  文件的概念 文件,对我们并不陌生,文件是数据源(保存数据的地方)的一种,比如大家经常使用的 word文档,txt文 件,excel 文件…都是文件。文件最主要的作用就是保存数据,它既可以保存一张图片,也可以保持视频,声 音… …