JavaScript高级 浏览器的渲染原理与JavaScript代码执行原理

news2024/11/14 14:26:00

浏览器的渲染原理

    • 1. 网页的解析过程
    • 2. 浏览器内核
      • 1. V8引擎
    • 3. 浏览器渲染过程
      • 1. HTML解析
      • 2. 生成CSS规则
      • 3. 构建Render Tree
      • 4. 布局(layout)
      • 5. 绘制(Paint)
    • 4. 回流和重绘解析
      • 1. 回流
      • 2. 重绘
      • 3. web 性能优化
      • 4. 合成和性能优化
    • 5. 浏览器遇到 script 元素的处理
    • 6. defer和async属性
      • 1. defer
      • 2. async
      • 3. 使用情况
    • 7. JavaScript代码执行原理
      • 1. 基于 ECMAScript3
      • 2. 基于 ECMAScript5
    • @ 相关文献资料

1. 网页的解析过程

客户端(浏览器)发起页面请求,主机对 地址中的DNS 域名进行解析,找到对应的 IP 地址,请求发送到 服务端,服务器根据请求内容发送响应给客户端,客户端收到响应,将内容渲染成网页。

在这里插入图片描述

2. 浏览器内核

我们经常说的浏览器内核指的是浏览器的排版引擎,排版引擎(layout engine),也称为浏览器引擎(browser engine)、页面渲染引擎(rendering engine)或样版引擎,也就是一个网页下载下来后,就是由我们的渲染引擎来帮助我们解析的

JavaScript代码下载好之后,是如何一步步被执行的呢?

我们知道,浏览器内核是由两部分组成的,以webkit为例

  • WebCore:负责HTML解析、布局、渲染等等相关的工作
  • JavaScriptCore:解析、执行JavaScript代码

另外一个强大的JavaScript引擎就是V8引擎

1. V8引擎

V8引擎的定义

V8是用C ++编写的Google开源高性能JavaScript和WebAssembly引擎,它用于Chrome和Node.js等

它实现ECMAScript和WebAssembly,并在Windows 7或更高版本,macOS 10.12+和使用x64,IA-32,ARM或MIPS处理器的Linux系统上运行

V8可以独立运行,也可以嵌入到任何C ++应用程序中
在这里插入图片描述

V8引擎的架构

V8引擎本身的源码非常复杂,大概有超过100w行C++代码,通过了解它的架构,我们可以知道它是如何对JavaScript执行的

  • Parse模块会将JavaScript代码转换成AST(抽象语法树),这是因为解释器并不直接认识JavaScript代码
    • 如果函数没有被调用,那么是不会被转换成AST的
    • Parse的V8官方文档:https://v8.dev/blog/scanner
  • Ignition是一个解释器,会将AST转换成ByteCode(字节码)
    • 同时会收集TurboFan优化所需要的信息(比如函数参数的类型信息,有了类型才能进行真实的运算)
    • 如果函数只调用一次,Ignition会解释执行ByteCode
    • Ignition的V8官方文档:https://v8.dev/blog/ignition-interpreter
  • TurboFan是一个编译器,可以将字节码编译为CPU可以直接执行的机器码
    • 如果一个函数被多次调用,那么就会被标记为热点函数,那么就会经过TurboFan转换成优化的机器码,提高代码的执行性能
    • 但是,机器码实际上也会被还原为ByteCode,这是因为如果后续执行函数的过程中,类型发生了变化(比如sum函数原来执行的是number类型,后来执行变成了string类型),之前优化的机器码并不能正确的处理运算,就会逆向的转换成字节码
    • TurboFan的V8官方文档:https://v8.dev/blog/turbofan-jit

解析流程

在这里插入图片描述
在这里插入图片描述

3. 浏览器渲染过程

渲染引擎解析整个页面并将其呈现
在这里插入图片描述

1. HTML解析

因为默认情况下服务器会给浏览器返回index.html文件,所以解析HTML是所有步骤的开始

解析HTML,会构建DOM Tree

2. 生成CSS规则

解析的过程中,如果遇到CSS的link元素,那么会由浏览器负责下载对应的CSS文件,下载CSS文件是不会影响DOM的解析的

浏览器下载完CSS文件后,就会对CSS文件进行解析,解析出对应的规则树

3. 构建Render Tree

当有了DOM Tree和CSSOM Tree后,就可以两个结合来构建Render Tree了

link元素不会阻塞DOM Tree的构建过程,但是会阻塞Render Tree的构建过程,这是因为Render Tree在构建时,需要对应的CSSOM Tree

Render Tree和DOM Tree并不是一一对应的关系,比如对于display为none的元素,压根不会出现在render tree

4. 布局(layout)

第四步是在渲染树(Render Tree)上运行布局(Layout)以计算每个节点的几何体,渲染树会表示显示哪些节点以及其他样式,但是不表示每个节点的尺寸、位置等信息,布局是确定呈现树中所有节点的宽度、高度和位置信息

5. 绘制(Paint)

第五步是将每个节点绘制(Paint)到屏幕上,在绘制阶段,浏览器将布局阶段计算的每个frame转为屏幕上实际的像素点,包括将元素的可见部分进行绘制,比如文本、颜色、边框、阴影、替换元素(比如img)

4. 回流和重绘解析

1. 回流

第一次确定节点的大小和位置,称之为布局(layout),之后对节点的大小、位置修改重新计算称之为回流

引起回流的方式

比如DOM结构发生改变(添加新的节点或者移除节点)

比如改变了布局(修改了width、height、padding、font-size等值)

比如窗口resize(修改了窗口的尺寸等)

比如调用getComputedStyle方法获取尺寸、位置信息

2. 重绘

第一次渲染内容称之为绘制(paint),之后重新渲染称之为重绘

引起重绘的方式

比如修改背景色、文字颜色、边框颜色、样式等

3. web 性能优化

回流一定会引起重绘,所以回流是一件很消耗性能的事情,所以在开发中要尽量避免发生回流

可以采用的操作

修改样式时尽量一次性修改,比如通过cssText修改,比如通过添加class修改

尽量避免频繁的操作DOM,我们可以在一个DocumentFragment或者父元素中将要操作的DOM操作完成,再一次性的操作

尽量避免通过getComputedStyle获取尺寸、位置等信息

对某些元素使用position的absolute或者fixed,并不是不会引起回流,而是开销相对较小,不会对其他元素造成影响。

4. 合成和性能优化

绘制的过程,可以将布局后的元素绘制到多个合成图层中,这是浏览器的一种优化手段

默认情况下,标准流中的内容都是被绘制在同一个图层,而一些特殊的属性,会创建一个新的合成层(CompositingLayer),并且新的图层可以利用GPU来加速绘制,因为每个合成层都是单独渲染的

分层确实可以提高性能,但是它以内存管理为代价,因此不应作为web 性能优化策略的一部分过度使用。

合成层的形成方式

3D transforms

video、canvas、iframe

opacity 动画转换时

position: fixed

will-change:一个实验性的属性,提前告诉浏览器元素可能发生哪些变化;

animation 或transition 设置了opacity、transform

5. 浏览器遇到 script 元素的处理

事实上,浏览器在解析HTML的过程中,遇到了script元素是不能继续构建DOM树的,它会停止继续构建,首先下载JavaScript代码,并且执行JavaScript的脚本,只有等到JavaScript脚本执行结束后,才会继续解析HTML,构建DOM树

延迟构建DOM树的原因

这是因为JavaScript的作用之一就是操作DOM,并且可以修改DOM,如果我们等到DOM树构建完成并且渲染再执行JavaScript,会造成严重的回流和重绘,影响页面的性能,所以会在遇到script元素时,优先下载和执行JavaScript代码,再继续构建DOM树

6. defer和async属性

在目前的开发模式中(比如Vue、React),脚本往往比HTML页面更“重”,处理时间需要更长,所以会造成页面的解析阻塞,在脚本下载、执行完成之前,用户在界面上什么都看不到,为了解决这个问题,script元素给我们提供了两个属性(attribute):defer和async

1. defer

defer 属性告诉浏览器不要等待脚本下载,而继续解析HTML,构建DOM Tree,脚本会由浏览器来进行下载,但是不会阻塞DOM Tree的构建过程,如果脚本提前下载好了,它会等待DOM Tree构建完成,在DOMContentLoaded事件之前先执行defer中的代码,所以DOMContentLoaded总是会等待defer中的代码先执行完成

多个带defer的脚本是可以保持正确的顺序执行的

从某种角度来说,defer可以提高页面的性能,并且推荐放到head元素中

2. async

async 特性与defer 有些类似,它也能够让脚本不阻塞页面

async是让一个脚本完全独立的,浏览器不会因async 脚本而阻塞,async脚本不能保证顺序,它是独立下载、独立运行,不会等待其他脚本,async不会能保证在DOMContentLoaded之前或者之后执行

3. 使用情况

defer通常用于需要在文档解析后操作DOM的JavaScript代码,并且对多个script文件有顺序要求的

async通常用于独立的脚本,对其他脚本,甚至DOM没有依赖的

7. JavaScript代码执行原理

1. 基于 ECMAScript3

2. 基于 ECMAScript5

@ 相关文献资料

How browsers work:https://web.dev/howbrowserswork/
在这里插入图片描述

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

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

相关文章

剑指offer----C语言版----第六天

目录 1. 用栈实现队列 1.1 题目描述 1.2 栈和队列的基础知识 1.3 思路分析 2. 扩展题目——用队列实现栈 2.1 题目描述 2.2 思路分析 1. 用栈实现队列 原题链接: 剑指 Offer 09. 用两个栈实现队列 - 力扣(LeetCode)https://leetcode.cn/…

数据结构集合框架与大O渐进表示法

作者:爱塔居的博客_CSDN博客-JavaSE领域博主 专栏:数据结构 作者简介:大三学生,希望跟大家一起进步!🌹 博客简介:了解数据结构,学习一些关于数据结构的前置知识 文章目录 目录 文章目…

【论文翻译】Deep Learning for Multi-view Stereo via Plane Sweep: A Survey(2021)

一、论文简述 1. 第一作者:Qingtian Zhu 2. 发表年份:2021 3. 发表期刊:CVPR 4. 关键词:MVS、深度学习、综述 5. 核心思想:读到的第一篇深度MVS的综述,总结的很好,内容涵盖了2021年前的研究…

遗传算法python进阶理解+论文复现(纯干货,附前人总结引路)

遗传算法python进阶理解论文复现(纯干货,附前人总结引路)一、简介和相关概念遗传算法简介相关概念介绍二、与其他智能优化算法的比较蚁群算法粒子群优化算法人工神经网络算法模拟退火算法鱼群算法三、必学知识(站在前人的肩膀上&a…

1214. 波动数列(推公式 + DP)

题目如下: 思路 or 题解: 我们可以设: 第一个数为 xxx d {a, -b} 那后续的数为:xd1x d_1xd1​ , xd1d)2x d_1 d_)2xd1​d)​2 … … xd1d2......dn−1x d_1 d_2 ... ... d_{n - 1}xd1​d2​......dn−1​ 根据题意和上面…

(Java高级教程)第二章Java多线程常见面试题-第三节:线程安全集合类和死锁

文章目录一:线程安全集合类(1)多线程环境下使用ArrayList(2)多线程环境使用队列(3)多线程使用哈希表二:死锁(1)概念(2)死锁产生的四个…

(小程序)会议OA项目-首页

目录 一、FIex布局简介 1.什么是flex布局? 2.flex属性 学习地址: 3.flex弹性布局演示 ① 容器的属性 ⑴ flex-direction属性 ⑵ flex-wrap属性 ⑶ flex-flow ⑷ justify-content属性 ⑸ align-items属性 ⑹ align-content属性 二、轮播图组件m…

微信记录怎么恢复?恢复已删除微信历史记录的4种方式

恢复已删除微信历史记录的4种方式 如何在有/没有备份的情况下在 iPhone 和 Android 上恢复旧的或已删除的微信历史记录,如聊天对话、语音消息、照片、图片和视频剪辑?参考本指南,祝您成功恢复微信数据。 关于微信数据恢复 “说真的&#xf…

容器化技术Docker与任务编排

Docker容器化 Docker简介 传统的Java项目部署需要自己进行打包,redis,nignx等中间件需要安装以及进行很多配置,稍微繁琐,而Docker使用了容器化的技术把这一过程封装为一条指令解决,而这取决于它的架构设计&#xff0c…

数值优化之函数高阶信息

本文ppt来自深蓝学院《机器人中的数值优化》 目录 1 函数高阶信息的介绍 2 函数高阶信息的计算 1 函数高阶信息的介绍 hessian矩阵是对称矩阵,最后一个公式是函数关于0的泰勒展开 负梯度是函数下降的最快方向 注意区分Hessian矩阵与Jacobian矩阵,Hess…

9_4、Java基本语法之System、Math、BigInteger与BigDecimal类的使用

一、System类的使用 1、System类代表系统,系统级的很多属性和控制方法都放置在该类的内部。 该类位于java.lang包。 由于该类的构造器是private的,所以无法创建该类的对象,也就是无法实 例化该类。其内部的成员变量和成员方法都是static的&am…

【算法题解】7. 反转链表

文章目录题目解法一:迭代解题思路代码实现复杂度分析解法二:递归解题思路代码实现复杂度分析题目 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。来自:leetcode 解法一:迭代 解题思路 使用…

广州车展智能卷王:集度ROBO-01的取与舍

作者 | 德新 编辑 | 王博2022年的最后两天,今年最后一个A级车展在广州开幕。由于种种原因,不少车企匆忙备战或者干脆缺席,这届展会不如往届热闹。但也有憋了大招的选手,比如集度。 12月30日上午,集度在一场非常短的发布…

11-内部类and 12-集合初步

文章目录11-内部类链接外部类使用.this 和.new匿名内部类12-集合初步思考1&#xff0c;List<Apple> apples new ArrayList<>();思考2&#xff0c;如何初始化一个collection思考3&#xff0c;Pet关键字思考4&#xff0c;关于ListIterator这个双向迭代器思考5&#…

保护性暂停设计模式

目录 保护性暂停设计模式 获取结果 产生结果 总代码实现 测试 增加超时效果的Guarded suspension get(long timeout) 测试 保护性暂停设计模式 Guarded Suspension 即 保护性暂停; 是一种等待唤醒机制的一种规范 ,也可以理解为使用中设计模式,Java的API很多都按照保护性…

【免费开放源码】审批类小程序项目实战(活动审批端)

第一节&#xff1a;什么构成了微信小程序、创建一个自己的小程序 第二节&#xff1a;微信开发者工具使用教程 第三节&#xff1a;深入了解并掌握小程序核心组件 第四节&#xff1a;初始化云函数和数据库 第五节&#xff1a;云数据库的增删改查 第六节&#xff1a;项目大纲以及制…

系分 - 面向对象的方法【概念】

个人总结&#xff0c;仅供参考&#xff0c;欢迎加好友一起讨论 系分 - &#xff08;概念&#xff09;面向对象的方法 面向对象的方法&#xff08;OO&#xff0c;Object-Oriented&#xff09;是一种基于对象模型的程序设计方法&#xff0c;包括面向对象的分析&#xff08;OOA&a…

【iOS】内存管理

文章目录前言理解引用计数引用计数原理属性存取方法中的内存管理自动释放池保留环以ARC简化引用计数使用ARC时必须遵守的命名规则变量的内存管理语义ARC如何清理实例变量覆写内存管理的方法在dealloc方法中只释放应用并解除监听前言 内存管理&#xff1a; 在Objective-C这样的…

Windows平台下的内存泄漏检测

Windows平台下的内存泄漏检测一、使用_CrtDumpMemoryLeaks定位内存泄露添加对应的头文件转储内存泄漏信息程序任意点退出指定调试信息输出二、定位具体内存泄露位置内存快照转储内存快照比较内存快照完整例子三、使用WinDbg定位获取堆信息查看指定堆的使用情况获取地址信息获取…

【Docker】初级篇

【Docker】初级篇&#xff08;一&#xff09;Docker简介【1】docker是什么【2】容器与虚拟机比较【3】能干嘛【4】去哪下&#xff08;二&#xff09;Docker安装【1】前提说明【2】Docker的基本组成【3】安装步骤&#xff08;1&#xff09;确定是CentOS7及以上版本&#xff08;2…