当前位置: 首页 > news >正文

前端 js 之 代码执行的一个过程 02

嘿,欢迎你来 !💕

文章目录

  • 前言
  • 一、运行一个 js 文件
  • 二、运行环境
  • 三、js执行代码的过程(普通变量)
  • 四、打印 window
  • 五、js执行代码的过程(函数变量)
  • 六、函数调用函数的过程
  • 注意!!!
  • 最后、作用域与作用域链面试题


前言


在上一篇文章里,我们简单说了浏览器的工作原理和v8引擎的原理



浏览器渲染

  1. 首先先下载 index.html ,遇到css 或者script 文件就下载,
  2. 通过浏览器内核进行解析 index.html
  3. 如果解析过程中遇到 js 代码就立即执行 js 代码,因为js代码属于高级语言,cpu不能直接执行,所以借助js引擎
  4. 对于v8 引擎来说,通过parse模块把我们的代码解析成 AST 树型结构,再通过ignation转化为字节码,再编译成低级语言,cpu就可以执行这些指令了

那今天我们研究的就是 js源代码到AST抽象语法树他进行解析,是如何解析的。


上篇文章整理了很久,多多少少有了点概念,今天这篇文章是基于上篇基础上的加深,希望我表达的足够清晰,如果错处,还望指正,感谢,biubiu ~💕


一、运行一个 js 文件


我们以下的讲解都是基于早期的ECMA的版本规范,也就es5之前的。也发现了所有的变量定义都是用的 var。

在早期的版本规定里是这样定义的:每个执行上下文都会被关联到一个变量环境(VO: variable Object,它是一个对象),源代码中的变量和函数都会 被作为属性 添加到VO中,对于函数来说,参数也会被添加到VO中

在最新的的ECMA 版本规范中,每个执行上下文会关联到一个变量环境中,在执行代码中变量和函数的声明会 作为环境纪录 添加到变量环境中,对于函数来说,参数也会被作为环境记录添加到环境变量中

const name = "haha";const name2 = "haha2";console.log(name);

假设这是一个 js 文件, 想在浏览器上运行,首先得有一个index.html ,通过script 引入才能运行。js引擎怎么运行的呢?


二、运行环境


我们编写的JS代码都是需要在一个环境中运行的:比如

  1. 浏览器(引擎):例如webkit,gecko,Trident, blink
  2. node*(基于V8渲染js)
  3. webview(v8引擎)
  4. JS之所以能够在浏览器中运行,是因为浏览器给JS提供了执行的环境 => 栈内存

先说几个概念:(不太理解也没关系)

  1. 栈内存 ( ECStack(Execution Context Stack):执行环境栈) :它是代码执行环境;它是浏览器分配的内存空间,用来执行代码 。
  2. 全局对象GO(Globle Object)): 该对象所有作用域都可以访问, 它用来存放当前环境的内置方法,类,变量等,他还有个window属性指向自己;这就是为什么我们可以直接使用Math,String,setTimeout 等方法 ,这里请注意!!对于方法,类这种复杂类型数据存放的是对应的内存地址,堆内存才是真正的存放代码
  3. 堆内存(Heap) :存放东西(属性和方法(例:isNaN:function…))
  4. 任何开辟的内存都有一个16进制的内存地址,方便后期找到这个内存,ox开头
  5. 执行上下文ECS(Execution Context stack) :在编程语言中,代码执行中,为了区分全局变量和函数执行所处的不同的作用域(目的是为了区分每个词法作用域下代码的独立性),会产生执行上下文栈,一个是全局执行上下栈 GEC,一个是函数执行上下文栈FEC,都会在ECS里运行
  6. 全局执行上下栈 GEC: 包括两部分,第一部分,在代码执行前,在paese转化为AST的过程中,会将全局定义的变量,函数等加入到 GO里,但是不会赋值(也称为变量的提升);第二部分,是代码的执行,变量赋值,或者执行函数等等
  7. 函数执行上下文栈FEC:包括三部分,第一部分,在解析函数成为AST树结构时,会创建一个AO,AO中包括形参、arguments、函数定义和指向函数对象、定义的变量;第二部分,作用域,由当前AO对象和父级VO组成,查找是会一层层查找;第三部分,this的绑定值(本篇先不说)

三、js执行代码的过程(普通变量)

const name = "haha";const name2 = "haha2";console.log(name);var golbalObject={String:'类',Date:'类',setTimeout:'方法',window:golbalObject,name:undefined,name2:undifined}
  1. 再代码被解析之前,运行之前,v8 引擎内部会帮助我们创建一个对象,全局变量(GlobalObject,又称为GO),
  2. 这个GlobalObject 存放着当前环境的全局对象,该对象所有的作用域都可以访问,
  3. 里面包括 Math,Date,settimeout…等 方法 ,还有一个 window属性 指向自己
  4. 在代码编译的时候,它可以确定我们定义了哪些变量,然后将这些变量添加到全局对象里面
  5. 因为我们还没有真正的执行,所以这些变量都是undefined(变量存放在GO) ,
  6. v8 为了执行代码,v8引擎内部会有一个全局执行上下文栈(全局代码需要被执行的时候才会创建,称为EGC),有且只有一个,EGC 包括两部分: 第一部分,称为VO,在代码执行前,在paese转化为AST的过程中,会将全局定义的变量,函数等加入到 GO里,但是不会赋值(也称为变量的提升),所以这个VO对应的是GO;第二部分,是代码的执行,变量赋值,或者执行函数等等
  7. 比如现在要执行 var name=30 这个代码;它就会去VO里面找,VO对应GO;再把GEC放到调用栈里执行

请添加图片描述


四、打印 window

const name = "haha";const name2 = "haha2";console.log(name);var golbalObject={String:'类',Date:'类',setTimeout:'方法',window:golbalObject,name:undefined,name2:undifined,}console.log(window)

当打印window时,发现这个对象包括很多东西,很多内置方法,包括name,name2等属性,是因为这个window指向时golbalObject,正如上面所说他一个window属性 指向自己

五、js执行代码的过程(函数变量)

1.   foo();2.   function foo() {3.      console.log("开心快乐向前冲");4.  }

提前声明 ps:

  1. 我们所有代码在执行前都要加载到内存里,(代码存放在磁盘,再进入内存,转化为机器语言,最后才能被cpu执行)
  2. 在内存里,会划分为栈结构和堆结构,简单类型数据放在栈里,复杂类型数据地址放在栈,值放在堆

运行的不仅仅是普通变量,那对于函数来说,他是一个怎么样的过程呢?

  1. 根据上面所说,在编译阶段,会把变量添加到全局对象里,在未运行之前值为undefined,
  2. 但是foo 在定义之前执行,但是能执行所有的代码,为什么可以打印出来foo呢?
  3. 因为是在编译,所以第一行代码没有执行;第二行发现声明了一个函数,他也会定义 foo在GO里,但是不同的是,因为函数较特殊,他会再开辟一个新的内存空间,用来存放函数, 函数执行上下文栈FEC(先理解这一块,下面会具体说) ,foo这里存放的就是函数对应的内存空间地址
  4. 理解成指针、引用,因为一个地址可以对应多个变量,也是为什么复杂类型数据会互相影响
  5. 以上是编译的过程,当执行到第二行时 foo() ,【请留意,他其实是两部分,foo 和()】,他会再VO (对应的是GO) 里面查找Foo,他发现是个内存地址,就会根据地址找到这个空间;()表示函数的执行,就会把我们 FEC 放入到 调用栈 里面执行。


请添加图片描述



为了不饶晕乎,我们先把以上理解清除,再往下看

1.   foo();2.   var name=1233.   function foo(num) {4.    	num=15.     console.log("开心快乐向前冲");6. 	console.log(name)7.  }
  1. 我们把对应的函数空间放到调用栈不是直接运行,而是创建一个函数执行上下文 :包括三部分,第一部分,在解析函数成为AST树结构时,会创建一个AO,AO中包括形参、arguments、函数定义和指向函数对象、定义的变量;第二部分,作用域,由当前AO对象和父级VO组成,查找是会一层层查找;第三部分,this的绑定值(本篇先不说);
  2. 在第六行的时候,我们发现在Ao 里面并没有name这个值,为什么使用了全局的name呢?
  3. 是这样的,当我们查找一个变量时,真实的查找路径是沿着作用域链来查找的
  4. 函数执行上下文不仅仅包括 **VO** ,还有一个 **scope chain** ,叫做作用域链 (看图二)
  5. 一个函数执行上下文的作用域链有两部份组成,当前 AO 的作用域 + 父级作用域
  6. (父级作用域在函数编译时就确定了)
  7. 他的执行顺序是:先在自己的函数执行上下文找,再向他的上级作用域找 所以你理解为什么可以使用name了吗 ?
  8. 一旦函数执行完毕,这个函数执行上下文就会弹出调用栈,就会销毁了,这个 ao 也因为没有指向也会被销毁掉
  9. 当再执行时,是重新创建了一个函数执行上下文,把以上的过程再走一遍



请添加图片描述




六、函数调用函数的过程

我们在上面看了普通变量的执行过程和函数的执行过程,其实发现很简单,调用栈帮我们执行代码,为了区分变量还是函数,我们使用全局执行上下文栈函数执行上下文栈帮助我们执行,编译过程中定义了,真正运行时才是会有赋值等操作。只有函数才有作用域,当我们在一个函数里使用了当前作用域没有定义的变量,而全局变量存在的变量时,也可以使用,是因为沿着作用域链来查找的。在函数定义的时候,他的内存地址里存放两个东西,一个是他的父级作用域和他的执行块

那我们现在看看函数调用函数的过程
其实也很简单,在函数里调用函数时,他发现有函数定义执行时,会再次创建一个函数执行上下文栈,用来存放新的函数,这个函数的VO 同样存储两个东西,一个是作用域(父级作用域和当前作用域)和代码块,如上,所以在函数里调用函数 ,也是按照作用域链查找变量,所以与定义的位置无关

注意!!!


        我们以上的讲解都是基于早期的ECMA的版本规范,也就es5之前的。也发现了所有的变量定义都是用的 var。

在早期的版本规定里是这样定义的: 每个执行上下文都会被关联到一个变量环境(VO: variable Object),再源代码中的变量和函数都会被作为属性添加到VO中,对于函数来说,参数也会被添加到VO中

在最新的ECMA版本规范中,进行了新的改动:每一个执行上下文会关联到一个变量环境中(variableEnvironment),在执行代码中变量和函数的声明会作为环境记录添加到变量环境中,对于函数来说,参数也会被作为环境记录添加到变量环境中

        通过上面的变化,我们可以得知,在最新的ECMA标准中,我们前面的变量对象VO已经有另外一个称呼环境变量,VE



在这里插入图片描述

最后、作用域与作用域链面试题

函数表达式遵循变量提升规则,
今天我的表达还可以吗?🤣

相关文章:

前端 js 之 代码执行的一个过程 02

嘿,欢迎你来 !💕 文章目录 前言一、运行一个 js 文件二、运行环境三、js执行代码的过程(普通变量)四、打印 window五、js执行代码的过程(函数变量)六、函数调用函数的过程注意!&…...

【经验分享】如何构建openGauss开发编译提交一体化环境

前文 本文适合对openGauss源代码有好奇心的爱好者,那么一个友好的openGauss源代码环境应该是怎么样的。openGauss的开发环境是如何设置的?openGauss的编译环境是如何构建的?如何向openGauss提交代码,笔者集合官方和几位博主实践提…...

儿童疫苗接种:安全与注意事项

引言: 儿童的疫苗接种是维护其健康和预防传染病的重要措施。疫苗可以有效地保护儿童免受各种疾病的威胁,但在接种过程中需要家长和监护人特别关注一些注意事项,以确保接种的安全性和有效性。本文将深入探讨儿童疫苗接种的重要性,…...

Go 代码块与作用域,变量遮蔽问题详解

Go 代码块与作用域详解 文章目录 Go 代码块与作用域详解一、引入二、代码块 (Block)2.1 代码块介绍2.2 显式代码块2.3 隐式代码块2.4 空代码块2.5 支持嵌套代码块 三、作用域 (Scope)3.1 作用域介绍3.2 作用域划定原则3.3 标识符的作用域范围3.3.1 预定义标识符作用域3.3.2 包代…...

可观测性-Metrics-WebClient异步Http远程Call

代码示例 1.依赖导入 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><ar…...

Android之播放本地视频和Url视频方法

一、播放本地视频文件 根据文件路径在浏览器中播放&#xff0c;可用于视频预览等场景 效果&#xff1a; 用浏览器播放本地视频 文件路径例子&#xff1a; /storage/emulated/0/Android/data/com.custom.jfrb/files/Movies/1697687179497.mp4 File file new File("文件…...

设计模式:工厂方法模式(C#、JAVA、JavaScript、C++、Python、Go、PHP):

本节主要介绍设计模式中的工厂方法模式。 简介&#xff1a; 工厂方法模式&#xff0c;它是对简单工厂模式的进一步抽象化&#xff0c;其好处是可以使系统在不修改原来代码的情况下引进新的产品&#xff0c;即满足开闭原则。 它定义了一个用于创建对象的工厂接口&#xff0c;让…...

C++基础——指针

1 概述 指针的作用&#xff1a;可以通过指针间接访问内存 内存编号从0开始&#xff0c;一般使用十六进制数字表示&#xff0c;指针可以保存地址 2 指针变量定义和作用 int main() {//1、指针的定义int a 10; //定义整型变量a//指针定义语法&#xff1a; 数据类型 * 变量名 …...

PLC 学习day02 硬件输入/输入的知识

1.资料来源 1.链接&#xff1a;三菱PLC视频教程全集之FX3U基本单元输入接线_哔哩哔哩_bilibili 2. 链接&#xff1a; 三菱plc视频教程全集之FX3U基本单元输出接线_哔哩哔哩_bilibili 2. PLC 的输入部分器件连接。 2.1 PLC输入部分的硬件知识 1. 一般输入部分是PLC获取信息的地…...

rabbitMq (2)

RabbitMQ 消息应答与发布 文章目录 1. 消息应答1.2 自动应答1.2 手动应答1.3 代码案例 2. RabbitMQ 持久化2.1 队列持久化2.2 消息持久化 3. 不公平分发4. 预取值分发5. 发布确认5.1 发布确认逻辑5.2 开启发布确认的方法5.3 单个确认发布5.4 批量确认发布5.5 异步确认5.5.1 处理…...

通讯协议学习之路:RS422协议理论

通讯协议之路主要分为两部分&#xff0c;第一部分从理论上面讲解各类协议的通讯原理以及通讯格式&#xff0c;第二部分从具体运用上讲解各类通讯协议的具体应用方法。 后续文章会同时发表在个人博客(jason1016.club)、CSDN&#xff1b;视频会发布在bilibili(UID:399951374) 一、…...

剪映failed to initialize,cuda.is_available()为false解决

debug记录帖 错误1&#xff1a;打开剪映发现弹窗提示failed to initialize graphics backed for D3D11 错误2&#xff1a;torch版本、cuda版本&#xff08;之前的正常环境&#xff09;都对但是torch.cuda.is_available()为false 怀疑是显卡驱动的问题 打开Nvidia Geforce Exp…...

基于Spring Boot的LDAP开发全教程

写在前面 协议概述 LDAP&#xff08;轻量级目录访问协议&#xff0c;Lightweight Directory Access Protocol)是一种用于访问和维护分布式目录服务的开放标准协议,是一种基于TCP/IP协议的客户端-服务器协议&#xff0c;用于访问和管理分布式目录服务&#xff0c;如企业内部的…...

在 Linux 上保护 SSH 服务器连接的 8 种方法

SSH 是一种广泛使用的协议&#xff0c;用于安全地访问 Linux 服务器。大多数用户使用默认设置的 SSH 连接来连接到远程服务器。但是&#xff0c;不安全的默认配置也会带来各种安全风险。 具有开放 SSH 访问权限的服务器的 root 帐户可能存在风险。尤其是如果使用的是公共 IP 地…...

摩尔信使MThings的协议转换(数据网关)功能

摩尔信使MThings可以作为现场总线&#xff08;RS485&#xff09;和以太网的数据中枢&#xff0c;并拥有强大的Modbus协议转换功能。 数据网关功能提供协议转换和数据汇聚功能&#xff0c;可实现多维度映射&#xff0c;包括&#xff1a;不同的通道(总线)类型、协议类型&#xff…...

Mac安装Kali保姆级教程

Mac安装Kali保姆级教程 其他安装教程&#xff1a;使用VMware安装系统Window、Linux&#xff08;kali&#xff09;、Mac操作系统 1 虚拟机安装VM Fusion 去官网下载VM Fusion 地址&#xff1a;https://customerconnect.vmware.com/en/evalcenter?pfusion-player-personal-13 …...

利用Spring Boot框架做事件发布和监听

一、编写事件 1.编写事件类并集成spring boot 事件接口&#xff0c;提供访问事件参数属性 public class PeriodicityRuleChangeEvent extends ApplicationEvent {private final JwpDeployWorkOrderRuleDTO jwpDeployWorkOrderRuleDTO;public PeriodicityRuleChangeEvent(Obje…...

KingBase库模式表空间和客户端认证(kylin)

库、模式、表空间 数据库 数据库基集簇与数据库实例 KES集簇是由单个KES实例管理的数据库的集合KES集簇中的库使用相同的全局配置文件和监听端口、共享相关的进程和内存结构同一数据库集簇中的进程、相关的内存结构统称为实例 数据库 数据库是一个长期存储在计算机内的、有…...

h5的扫一扫功能 (非微信浏览器环境下)

必须在 https 域名下才生效 <template><div><van-field label"服务商编码" right-icon"scan" placeholder"扫描二维码获取" click-right-icon"getCameras" /> <div class"scan" :style"{disp…...

Typora 导出PDF 报错 failed to export as pdf. undefined 解决方案

情况 我想把一个很大的markdown 导出为 248页的pdf 然后就报错 failed to export as pdf. undefined 原因 &#xff1a; 个人感觉应该是图片太大了 格式问题之类导致的 解决 文件 -> 偏好设置 - > 导出 -> pdf -> 自定义 -> 把大小全部改为24mm (虽然图中是32 …...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

Python:操作 Excel 折叠

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成

厌倦手动写WordPress文章&#xff1f;AI自动生成&#xff0c;效率提升10倍&#xff01; 支持多语言、自动配图、定时发布&#xff0c;让内容创作更轻松&#xff01; AI内容生成 → 不想每天写文章&#xff1f;AI一键生成高质量内容&#xff01;多语言支持 → 跨境电商必备&am…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...