JavaScript(JS)是一种广泛使用的编程语言,特别是在Web开发中。在浏览器中,JS被用于实现动态网页效果、交互性和用户体验的提升。然而,要理解JS在浏览器中的工作原理,我们首先需要了解浏览器的渲染过程。
浏览器渲染过程可以分为以下几个步骤:
1. 解析HTML:当浏览器接收到HTML文档时,它会将其解析成DOM(文档对象模型)树。DOM树是由HTML标签和它们之间的关系构成的树状结构,表示了文档的结构和内容。
2. 解析CSS:浏览器会解析HTML文档中的CSS样式表,将其转换为CSS对象模型(CSSOM)。CSSOM表示了文档的样式信息,包括颜色、字体、布局等。
3. 构建渲染树:浏览器将DOM树和CSSOM合并,生成渲染树。渲染树只包含需要显示在屏幕上的元素,隐藏的元素不会被包含在渲染树中。渲染树中的每个节点都包含了元素的样式和布局信息。
4. 布局(重排):浏览器根据渲染树的布局信息,计算每个元素在屏幕上的位置和大小。这个过程被称为布局或重排。布局是一个计算密集型的过程,因为它需要考虑到元素的大小、位置和相互关系。
5. 绘制(重绘):在布局完成后,浏览器将渲染树中的元素转换为屏幕上的像素。这个过程被称为绘制或重绘。绘制过程包括将元素的样式应用到像素上,并将它们绘制到屏幕上。
6. 合成:在绘制完成后,浏览器将绘制的图像合成为一张或多张位图,然后在屏幕上显示。合成过程包括将位图合并、处理透明度和混合等操作。
在这个过程中,JS的执行会影响到渲染的进行。当浏览器遇到JS代码时,它会停止渲染过程,执行JS代码,然后再继续渲染。这是因为JS可以修改DOM树和CSSOM,从而影响到渲染树的构建和布局。
为了提高性能,浏览器会对JS代码进行优化。例如,浏览器会将JS代码解析为字节码或机器码,以提高执行速度。此外,浏览器还会使用异步加载和延迟加载等技术,将JS代码的下载和执行与渲染过程分离,以避免阻塞页面的加载和渲染。
js的加载
1.遇到script标签,如果有src发请求获取js,执行js完毕后在解析后续标签
2.js的加载和执行会阻塞后续标签的解析
3.页面中多个js运行并行下载顺序执行,页面中的js会并行加载,只要js加载完成后立马执行,到那时如果某个js如果已经下载完成但前一个js还没下载执行,那么它必须等前面js下载执行完后才执行
4.建议引入js文件放置在body内部的末尾,让dom尽快展现,同时方便js操作dom
css加载
1.遇到link标签,会发送请求获取css,同时不影响后续标签的解析
2.css的加载不阻塞解析,但是会阻塞渲染:解释:不阻塞解析指不影响dom树的创建,阻塞渲染是因为css未加载完成导致cssom树为创建完成,从而无法构建渲染树,一直处于白屏状态
3.建议把进入css文件放置在head标签内,尽可能早的加载css
saync与defer
1.正常情况下js的加载会阻止dom结构的创建,并且js会按顺序执行
<scrpt astnc src="script,js"></script>
async:加载和渲染后续文档元素的过程将和script.js的加载并行进行(异步)
<script defer src="script.js"></script>
defer:加载后续文档元素的过长将和script.js的加载并行进行(异步),但script.js的执行要在所有元素解析完成后执行
2.差异:async的存在不影响dom的解析和其他资源的加载,特例独行,不保证顺序,不保证时机
defer:defer存在不影响dom的解析和其他资源的加载,但是会保证在dom资源准备就绪后在执行,并且对于多个defer的位外置js按顺序执行
url输出到页面展现流程:
1、DNS域名解析
在浏览器输入我们的网址域名 比如www.baidu.com,并不是百度真实的地址,互联网中每一台机器都有唯一标识的ip地址。网址和ip地址的转换,就是DNS解析。
需要获取到域名的对应IP,需要访问域名服务器,域名服务器访问流程大致如下:
查找浏览器缓存 —> 查找操作系统缓存 —> 查找路由器缓存 —> 查找本地DNS缓存 —> 递归查询
- 完整的url:协议+域名+端口+路径[+参数] [+描点]
- 解析url是因为某些参数包含的特殊字符会产生歧义,url对非安全字符转义,用的是百分号编码
- encodeURL 不会编译= ? & ;/等符号,所以用来编码整个URL;而encodeURLComponent编码会编译以上特殊字符,所以用来编码参数部分
2、建立TCP连接
1、服务端新建套接字,绑定地址信息后开始监听,进入LISTEN状态。客户端新建套接字绑定地址信息后调用connect,发送连接请求SYN,并进入SYN_SENT状态,等待服务器的确认。
2、服务端一旦监听到连接请求,就会将连接放入内核等待队列中,并向客户端发送SYN和确认报文段ACK,进入SYN_RECD状态。
3、客户端收到SYN+ACK报文后向服务端发送确认报文段ACK,并进入ESTABLISHED状态,开始读写数据。服务端一旦收到客户端的确认报文,就进入ESTABLISHED状态,就可以进行读写数据了。
三次握手想要达到什么样的目的
①客户端发送网络包,服务端收到了。 这样服务端就能得出结论:客户端的发送能力、服务端的接收能力是正常的。
②服务端发包,客户端收到了。 这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。不过此时服务器并不能确认客户端的接收能力是否正常
③客户端发包,服务端收到了。 这样服务端就能得出结论:客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常。
3、客户端发送HTTP请求
http是基于tcp的,所以只有在建立了tcp以后,客户端才能向服务器发起http请求。这个请求报文会包括这次请求的信息,主要是请求方法,请求说明和请求附带的数据,并将这个 http 请求封装在一个 tcp 包中;这个 tcp 包也就是会依次经过传输层,网络层, 数据链路层,物理层到达服务器,服务器解析这个请求来作出响应;返回相应的 html 给浏览器;
4、服务器处理请求
后端从在固定的端口接收到TCP报文开始,它会对TCP连接进行处理,对HTTP协议进行解析,并按照报文格式进一步封装成HTTP Request对象,供上层使用。
5、服务器响应请求
通常请求的方式(get或post) + 请求的资源的位置(url) + HTTP客户端与服务器之前建立链接,收到服务器的返回比如index.html资源
发送http请求过程:组装http报文并将报文发向指定地址的过程服务器处理并返回HTTP报文
6、浏览器解析html
1. 浏览器解析HTML,构建DOM树
2. 浏览器解析css,构建CSS Rule Tree规则树
3. 解析完成后,浏览器引擎根据DOM树和CSS规则构造Render Tree(不包括Header、display:none)
4. 根据Render Tree布局lay out,计算节点
5. 遍历Render Tree绘制paint
浏览器发送请求获取嵌入在 HTML 中的资源(如图片、音频、视频、CSS、JS等等),这与获取html一样,都是一个个http请求,全部获取到后,页面才算完整了,浏览器变将一个完整的页面渲染屏幕上。
7、断开TCP连接(4次挥手)
1.客户端主动调用close时,向服务端发送结束报文段FIN报,同时进入FIN_WAIT1状态;
2.服务器会收到结束报文段FIN报,服务器返回确认报文段ACK并进入CLOSE_WAIT状态,此时如果服务端有数据要发送的话,客户端依然需要接收。客户端收到服务器对结束报文段的确认,就会进入到FIN_WAIT2状态,开始等待服务器的结束报文段;
3.服务器端数据发送完毕后,当服务器真正调用close关闭连接时,会向客户端发送结束报文段FIN包,此时服务器进入LAST_ACK状态,等待最后一个ACK的带来;
4.客户端收到服务器发来的结束报文段, 进入TIME_WAIT, 并发出送确认报文段ACK;服务器收到了对结束报文段确认的ACK,进入CLOSED状态,断开连接。而客户端要等待2MSL的时间,才会进入到CLOSED状态。