- 网页被解析的过程
- 浏览器的内核
渲染页面的详细流程:www.html5rocks.com/en/tutorial…
- 构建Render Tree(渲染树)
- link元素不会阻塞DOM树的构建过程,但是会阻塞渲染树的构建过程
- 渲染树和DOM树并不是一一对应的关系,比如display为none的元素,压根不会出现在渲染树中
总结:
- 首先通过DNS服务器进行域名解析
- 解析出对应的IP地址 然后从ip地址对应的主机发送http请求 获取对应的静态资源
- 默认情况服务器会返回index.html文件
- 然后浏览器内核开始解析HTML
- 首先 会解析对应的html 生成DOM Tree
- 解析过程中 如果遇到css的link标签 则会下载对应的css文件
- 下载css文件和生成DOM树是同时进行
- 下载完对应的css文件后会进行css解析 生成CSSOM( CSS object model)
- 当DOM Tree和CSSTree都解析完成之后 会进行合并用来生成Render Tree(渲染树)
- 初步生成的渲染树会显示节点以及部分样式 但是并不表示每个节点的尺寸 位置信息 于是进行Layout(布局)来生成渲染树中节点的宽度 高度位置信息
- 经过Layout之后 浏览器内核将布局时的每个frame转屏幕上的每个像素点 将每个节点绘制到屏幕上
回流和重绘
第一次确定节点大小和位置,称之为布局之后对节点的大小、位置修改重新计算称之为
回流
尽量避免发生回流:
- 修改样式时尽量一次性修改,比如通过cssText修改,比如通过添加class修改
- 尽量避免频繁的操作DOM
- 尽量避免通过getComputedStyle获取尺寸、位置等信息
- 对某些元素使用position的absolute或者fixed并不是不会引起回流,而是开销相对较小,不会对 其他元素造成影响
第一次渲染内容称之为绘制(paint),之后重新渲染称之为
重绘,比如修改背景色、文字颜色、边框颜色、样式等会引起重绘
- defer属性
defer 属性告诉浏览器不要等待脚本下载,而继续解析HTML,构建DOM Tree
- 脚本会由浏览器来进行下载,但是不会阻塞DOM Tree的构建过程;
- 脚本提前下好了,会等待DOM树构建完成,在DOMContentLoaded事件之前先执行defer中的代码
- defer可以提高页面的性能,并且推荐放到head元素中
- 注意:defer仅适用于外部脚本,对于script默认内容会被忽略
- async属性
async它也能够让脚本不阻塞页面,是让一个脚本完全独立的
- 浏览器不会因 async 脚本而阻塞(与 defer 类似
- async脚本不能保证顺序,它是独立下载、独立运行,不会等待其他脚本
- async不能保证在DOMContentLoaded之前或者之后执行
defer通常用于需要在文档解析后操作DOM的JavaScript代码,并且对多个script文件有顺序要求的;
async通常用于独立的脚本,对其他脚本,甚至DOM没有依赖的;
JS运行原理
- V8引擎
Parse模块会将JavaScript代码转换成AST(抽象语法树),如果函数没有被调用,是不会被转换成AST
Ignition是一个解释器,会将AST转换成ByteCode(字节码)
TurboFan是一个编译器,可以将字节码编译为CPU可以直接执行的机器码
- 初始化全局对象
js引擎会在执行代码之前,会在堆内存中创建一个全局对象:
Global Object(GO)
- 该对象 所有的作用域(scope)都可以访问
- 里面会包含Date、Array、String、Number、setTimeout、setInterval等等
- 其中还有一个window属性指向自己
- 执行上下文
js引擎内部有一个执行上下文栈(Execution Context Stack,简称ECS),用于执行代码的调用栈
每一个执行上下文会关联一个VO(
Variable Object,变量对象),变量和函数声明会被添加到这个VO对象中
当全局代码被执行的时候,VO就是GO对象了
在执行的过程中执行到一个函数时,就会根据函数体创建一个函数执行上下文(Functional Execution Context,简称FEC),并且压入到执行上下文中
- 当进入一个函数执行上下文时,会创建一个AO对象(Activation Object);
- 这个AO对象会使用arguments作为初始化,并且初始值是传入的参数;
- 这个AO对象会作为执行上下文的VO来存放变量的初始化;
总结:
- 首先在执行前会在堆内存中开辟一块空间(GO) 存放一些初始的值 如Number String等等
- 代码中定义的一些变量 函数 ( 在解析器转成抽象语法树的过程中存放在GO中的 ) 并没有赋值
- 同时在执行代码时在执行上下文栈(ECS)中存放一个全局执行上下文(GEC) 用于执行代码
- GO中对应的函数也会在堆内存中开辟出空间为 Function Object 初始一些数据(name length scope chain等)
- 开始执行代码
- 每个EC中有着三个重要的内容(VO scope chain 以及this)
- VO指向对应的作用域(全局作用域(GO) 函数作用域(AO))
作用域和作用域链
作用域链是一个
对象列表,用于变量标识符的求值;当进入一个执行上下文时,这个作用域链被创建,并且根据代码类型,添加一系列的对象