浏览器
浏览器是如何解析代码的?
-
解析HTML
- HTML的解析是逐行解析。
- 构建DOM树
-
解析css
- CSS选择器的读取顺序是从右向左
- 因此浏览器会按照从右向左的顺序去读取选择器
-
解析js
- 浏览器中有一个js解析器的工具,专门用来解析我们的js代码
- 解析器会找到js当中的所有变量、函数、参数等等
浏览器是如何解析JS代码和执行的
V8 引擎执行 JS 代码
- 解析阶段:V8引擎将JS代码 转换 为
AST抽象语法树 AST抽象语法树 转换为字节码- 字节码再转换为机器码
浏览器工作原理
浏览器的工作原理可以分为以下几个步骤:
- 输入网址:当你在浏览器的地址栏输入网址时,浏览器会向服务器请求该网址的内容。
- 服务器响应请求:服务器会返回网站的内容,这些内容通常包含 HTML、CSS 和 JavaScript 代码。
- 浏览器解析 HTML:浏览器会读取 HTML 代码,并根据这些代码在屏幕上显示出网站的内容。
- 浏览器解析 CSS:浏览器会读取 CSS 代码,并根据这些代码设置网站的样式。
- 浏览器执行 JavaScript:浏览器会读取 JavaScript 代码,并执行这些代码。JavaScript 可以用来控制网站的行为,例如动态地改变网站的内容或添加交互功能。
- 浏览器渲染内容
浏览器的渲染机制 【页面渲染html的过程】
浏览器工作流程:构建DOM -> 构建CSSOM -> 构建渲染树 -> 布局 -> 绘制。
1、构建DOM树(parse):渲染引擎解析HTML文档,首先将标签转换成DOM树中的DOM node
- 解析HTML文档,将其中的标签、属性、文本转换为DOM树 【DOM树表示网页的结构】
2、构建渲染树(construct):解析对应的CSS样式文件信息
- 浏览器会去解析css样式,计算每个元素的样式信息
3、布局渲染树 (reflow/layout)
- 从根节点递归调用,计算每一个元素的大小、位置,来得出元素在屏幕上的准确显示位置
4、绘制渲染树(paint/repaint)
- 遍历渲染树,浏览器将每个节点转换为屏幕上的实际像素
1、解析html构建dom树
2、解析css构建render树(将CSS代码解析成树形的数据结构,然后结合DOM合并成render树)
3、布局render树(Layout/reflow),负责各元素尺寸、位置的计算
4、绘制render树(paint),绘制页面像素信息
5、渲染树创建好了,浏览器就可以根据渲染树把页面绘制到屏幕上。
- 渲染好的东西绘制页面上面去显示给用户
浏览器遇到什么会停下来
阻塞发生的情况:
- 遇到script标签加载js的时候会加载js并且执行完毕才开始渲染
- 因为js会对DOM进行操作,所以js阻塞DOM树的构建
- 遇到js浏览器会停下来DOM构建,所以最好把js放在body底部
- 其中一个原因就是为了不阻塞浏览器DOM树的构建,这也是为什么放在body上面的JS常常取不到想要的DO M节点,因为这个时候DOM树的构建还没有完成就被阻塞了
- 当浏览器遇到一个 script 标记时,DOM 构建将暂停,直至脚本完成执行
- 遇到alert会阻塞
- css也会阻塞
- css是由单独的下载线程异步下载的。
总结:
js会阻塞DOM的构建,一般js放在body底部
css加载不会阻塞DOM树的解析 css加载会阻塞渲染树(render树)的构建 css加载会阻塞后面js语句的执行
尽可能的提高css加载速度
- 使用CDN
- 对css进行压缩
- 减少http请求数
理解浏览器沙箱
- 沙箱:就是一个环境,黑盒,在一个虚拟的环境中模拟真实世界,不对外界进行干扰
沙箱,即sandbox,顾名思义,就是让你的程序跑在一个隔离的环境下,不对外界的其他程序造成影响,通过创建类似沙盒的独立作业环境,在其内部运行的程序并不能对硬盘产生永久性的影响
- 举个简单的例子,其实我们的浏览器,Chrome 中的每一个标签页都是一个沙箱(sandbox)。渲染进程被沙箱(Sandbox)隔离,网页 web 代码内容必须通过 IPC 通道才能与浏览器内核进程通信,通信过程会进行安全的检查。沙箱设计的目的是为了让不可信的代码运行在一定的环境中,从而限制这些代码访问隔离区之外的资源
- IPC是Inter-Process Communication的缩写 ,含义为进程间通信或者跨进程通信,是指两个进程之间进行数据交换的过程。
JS实现沙箱两种方式
- 市面上现在流行两种沙箱模式,一种是使用iframe,还有一种是直接在页面上使用new Function + eval进行执行
为什么在一个浏览器中使用多个进程
每个进程内都有什么
在什么情况下浏览器会创建进程
浏览器安全控制
-
X-XSS-Protection
- 防止反射型XSS
-
Strict-Transport-Security
- 强制使用HTTPS通信
-
CSP: 使用 W3C 提出的
CSP (Content Security Policy,内容安全策略),定义域名白名单内容安全策略 (CSP, Content Security Policy) 是一个附加的安全层,用于帮助检测和缓解某些类型的攻 击,包括跨站脚本 (XSS) 和数据注入等攻击。 这些攻击可用于实现从数据窃取到网站破坏或作为恶意软 件分发版本等用途。
CSP 本质上就是建立白名单,开发者明确告诉浏览器哪些外部资源可以加载和执行。我们只需要配置规则,如何拦截是由浏览器自己实现的。我们可以通过这种方式来尽量减少XSS 攻击
- HTTP 响应头 Content-Security-Policy 允许站点管理者在指定的页面控制用户代理的资源。除了少数例外,这条政策将极大地指定服务源 以及脚本端点。这将帮助防止跨站脚本攻击(Cross-Site Script) (XSS).
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
浏览器内核的理解
主要分成两部分:渲染引擎(layout engineer或Rendering Engine)和JS引擎。 渲染引擎:负责取得网页的内容(HTML、XML、图像等等)、整理讯息(例如加入CSS等),以及计算网页的显示方式,然后会输出至显示器或打印机。
浏览器的内核的不同对于网页的语法解释会有不同,所以渲染的效果也不相同。所有网页浏览器、电子邮件客户端以及其它需要编辑、显示网络内容的应用程序都需要内核。
JS引擎则:解析和执行javascript来实现网页的动态效果。 最开始渲染引擎和JS引擎并没有区分的很明确,后来JS引擎越来越独立,内核就倾向于只指渲染引擎。
谈谈你对重绘和回流的理解。
回流也叫重排: 简单来说,就是当我们对 DOM 的修改引发了 DOM 几何尺寸的变化(比如修改元素的宽、高或隐藏元素等)时,浏览器需要重新计算元素的几何属性(其他元素的几何属性和位置也会因此受到影响),然后再将计算的结果绘制出来。这个过程就是回流(也叫重排)。- 重绘:当我们对 DOM 的修改导致了样式的变化、却并未影响其几何属性(比如修改了颜色或背景色)时,元素的位置信息不需要更新. 浏览器不需重新计算元素的几何属性、直接为该元素绘制新的样式(跳过了上图所示的回流环节)。这个过程叫做重绘。
这也是为什么操作DOM是昂贵的,因为会触发浏览器的渲染 【重绘和回流】,更加消耗性能
触发回流
1、一个 DOM 元素的几何尺寸变化,常见的几何属性有 width、height、padding、margin、left、top、border 等等, 这个很好理解。
2、使 DOM 节点发生 增减或者 移动。
3、读写 offset族、scroll族和 client族属性的时候,浏览器为了获取这些值,需要进行回流操作。
4、调用 window.getComputedStyle 方法。
- 包含的任何基本计算后元素的所有CSS属性的值
知道了重绘和回流,在开发中有什么意义呢?
由此我们可以看出, 重绘不一定导致回流,回流一定会导致重绘, 但这两个说到底都是吃性能的 ,我们在开发中,要从代码层面出发,尽可能把回流和重绘的次数最小化。
当一个DOM元素的几何属性发生变化时,所有和它相关的节点(比如父子节点、兄弟节点等)的几何属性都需要进行重新计算,它会带来巨大的计算量。
当你要用到像这样的属性:offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight 时,你就要注意了!
- (获取元素布局宽度/高度,获取元素相对视口的位置,获取屏幕宽度/高度)
- 因为获取这些值,浏览器是要通过即时计算的,因此会触发回流
- 除此之外,当我们调用了 getComputedStyle 方法,或者 IE 里的 currentStyle 时,也会触发回流。原理是一样的
-
避免频繁使用 style,而是采用修改
class的方式。- 因为每次使用style修改样式,都会去触发一次渲染树的更改,从而导致相应的回流与重绘过程
- 而我们把所有样式操作合并在一个class中,等于我们将所有的更改一次性发出,只触发一次渲染树
-
使用
createDocumentFragment进行批量的 DOM 操作。 -
对于 resize、scroll 等进行防抖/节流处理。
-
添加 will-change: tranform ,让渲染引擎为其单独实现一个图层,当这些变换发生时,仅仅只是利用合成线程去处理这些变换,而不牵扯到主线程,大大提高渲染效率。当然这个变化不限于
tranform, 任何可以实现合成效果的 CSS 属性都能用will-change来声明。这里有一个实际的例子,一行will-change: tranform拯救一个项目,点击直达 -
使用translate替代position
- 改变 position 是会导致浏览器进行重排,浏览器会重新计算受到影响的元素的几何位置,这种计算量是非常巨大的且慢的
- translate不会触发回流
浏览器的Flush队列
因为现代浏览器是很聪明的。浏览器自己也清楚,如果每次 DOM 操作都即时地反馈一次回流或重绘,那么性能上来说是扛不住的。于是它自己缓存了一个 flush 队列,把我们触发的回流与重绘任务都塞进去,待到队列里的任务多起来、或者达到了一定的时间间隔,或者“不得已”的时候,再将这些任务一口气出队
- 何为 “不得已”的时候 ? 上面我们提到一些属性,即当你要用到像这样的属性:offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight 时,你就要注意了!,它们有很强的
即时性,当我们访问这些属性时,浏览器会为了获得此时此刻的、最准确的属性值,而提前将 flush 队列的任务出队——这就是所谓的“不得已”时刻
浏览器垃圾回收
浏览器怎么进行垃圾回收
标记清除算法,GC会检测当前对象有没有被变量所引用,如果没有就回收
从三个点来回答什么是垃圾、如何捡垃圾、什么时候捡垃圾。
- 什么是垃圾
- 不再需要,即为垃圾
- 全局变量随时可能用到,所以一定不是垃圾
- 如何捡垃圾(遍历算法)
- 标记空间中「可达」值。
- 从根节点(Root)出发,遍历所有的对象。
- 可以遍历到的对象,是可达的(reachable)。
- 没有被遍历到的对象,不可达的(unreachable)
- 回收「不可达」的值所占据的内存。
- 做内存整理。
- 标记空间中「可达」值。
- 什么时候捡垃圾
- 前端有其特殊性,垃圾回收的时候会造成页面卡顿。
- 分代收集、增量收集、闲时收集。
浏览器中不同类型变量的内存都是何时释放?
Javascritp 中类型:值类型,引用类型。
- 引用类型
- 在没有引用之后,通过 V8 自动回收。
- 值类型
- 如果处于闭包的情况下,要等闭包没有引用才会被 V8 回收。
- 非闭包的情况下,等待 V8 的新生代切换的时候回收。
哪些情况会导致内存泄露?如何避免?
内存泄露是指你「用不到」(访问不到)的变量,依然占居着内存空间,不能被再次利用起来。
以 Vue 为例,通常有这些情况:
- 监听在
window/body等事件没有解绑 - 绑在
EventBus的事件没有解绑 Vuex的$store,watch了之后没有unwatch- 使用第三方库创建,没有调用正确的销毁函数
解决办法:beforeDestroy 中及时销毁
- 绑定了
DOM/BOM对象中的事件addEventListener,removeEventListener。 - 观察者模式
$on,$off处理。 - 如果组件中使用了定时器,应销毁处理。
- 如果在
mounted/created钩子中使用了第三方库初始化,对应的销毁。 - 使用弱引用
weakMap、weakSet。
闭包会导致内存泄露吗?
顺便说一个我在了解垃圾回收之前对闭包的误解。
闭包会导致内存泄露吗?正确的答案是不会。
内存泄露是指你「用不到」(访问不到)的变量,依然占居着内存空间,不能被再次利用起来。
闭包里面的变量就是我们需要的变量,不能说是内存泄露。
这个误解是如何来的? 因为 IE。IE 有 bug,IE 在我们使用完闭包之后,依然回收不了闭包里面引用的变量。 这是 IE 的问题,不是闭包的问题。 参考这篇
浏览器数据库 IndexedDB
- IndexedDB 就是浏览器提供的本地数据库
- 在用户的浏览器内持久化存储数据的方法
- 允许储存大量数据
浏览器缓存方案
- 强缓存
- 协商缓存
- localStorage与sessionStorage
- IndexedDB浏览器数据库,存储空间大小是根据你当前硬盘内存来决定
浏览器的SameSite
Chrome 51 开始,浏览器的 Cookie 新增加了一个SameSite属性,用来防止 CSRF【跨站请求伪造】 攻击和用户追踪http
浏览器如何识别资源类型
- 浏览器会通过 HTTP响应头中的
Content-Type字段,来确定资源的类型- Content-Type表示内容类型
如
- text/html : HTML格式
- text/plain :纯文本格式
- text/xml : XML格式
- image/gif :gif图片格式
- image/jpeg :jpg图片格式
- image/png:png图片格式