网络与浏览器
缓存
在浏览器中,一个页面从输入URL到加载完成,都有哪些步骤?
GET 和 POST 的区别有哪些?
参考了这几篇文章
在看到GET和POST:辩证看100 continue,以及最根本区别这篇文章之前,我也刚好刚看完99%的人都理解错了HTTP中GET与POST的区别这篇文章,但是看完之后又让我更加深入地了解了GET和POST!!!
文章2得出了两个言简意赅的结论:
GET产生一个TCP数据包;POST产生两个TCP数据包
对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200;对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok
文章3对文章2的结论提出了一些疑问,主要是关于首部Expect: 100-continue的区别。《HTTP权威指南》这样P62和附录C这样解释道
100 continue的目的是对HTTP客户端应用程序有一个实体的主体部分要发送到服务器,但希望在发送之前查看一下服务器是否会接受这个实体这种情况进行优化
客户端
如果客户端在向服务器发送一个实体,并愿意在发送实体之前等待100 continue响应,那么客户端就要发送一个携带了值为100 continue的Except请求首部。如果客户端没有发送实体,就不应该发送100 continue Except首部,因为这样会使服务器误以为客户端要发送一个实体
认真看这个地方,就会发现跟文章2中的区别,这里是客户端愿意发100 continue才会有响应,并不是每次都会有100 continue响应,再对比一下文章2的结论
对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok
区别就在这里
服务器端
如果服务器收到一条带有值为100 continue的Except首部的请求,它会用100 continue响应或一条错误码来进行响应。服务器永远也不应该向没有发送100 continue期望的客户端发送100 continue状态码。 如果服务器在有机会发送100 continue响应之前就收到了部分(或者全部)的实体,说明服务器已经打算继续发送数据了,这样服务器就不需要发送这个状态码了,但是服务器完成请求之后,还是应该为请求发送一个最终状态码。
文章3得出的结论是
通过抓包发现,尽管会分两次,body就是紧随在header后面发送的,根本不存在『等待服务器响应』这一说
这里是W3C的对比HTTP 方法:GET 对比 POST

首先,GET和POST是由HTTP协议定义的,Method和Data(URL,Body,Header)这两个概念没有必然的联系,使用哪个Method与应用层的数据如何传输是没有相互关系的。
HTTP没有要求,如果是POST,数据就要放在BODY中。也没有要求GET,数据(参数)就一定要放在URL中而不能放在BODY中。
HTTP协议明确地指出了,HTTP头和Body都没有长度的要求,URL长度上的限制主要是由服务器或浏览器造成的。
在用法上,一个用于获取数据,一个用于修改数据
在根本上,二者并没有什么区别
在细节上,有一些区别,需要展开讲吗?
回流(Reflow)与重绘(Repaint)
当 Render Tree 中部分或全部元素的规模尺寸,结构或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为 回流。每个页面至少需要一次回流,就是页面第一次加载的时候。在回流的时候,浏览器会使 Render Tree 中受到影响的部分失效,并重新构造这部分Render Tree,完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程称为 重绘。
当页面中元素样式的改变并不影响它在文档流中的位置时,浏览器会将新样式赋予给元素并重新绘制它,这个过程称为 重绘。
总结:回流必将引起重绘,而重绘不一定会引起回流。
回流何时发生?
- 添加或者删除可见的 DOM 元素
- 元素位置发生改变
- 元素尺寸改变——边距、填充、边框、宽度和高度
- 内容改变——比如文本或者图片大小改变而引起的计算值宽度和高度改变
- 页面渲染初始化
- 浏览器窗口尺寸改变
举个栗子🌰
var s = document.body.style;
s.padding = "2px"; // 回流+重绘
s.border = "1px solid red"; // 回流+重绘
s.color = "blue"; // 重绘
s.backgroundColor = "#CCC"; // 重绘
s.fontSize = "14px"; // 回流+重绘
// 添加node,回流+重绘
document.body.appendChild(document.createTextNode("abc!"));
性能影响
回流比重绘的代价更高。
有时即使仅仅回流一个单一的元素,它的父元素以及任何跟随它的元素也会发生回流。
现代浏览器会对频繁的回流或重绘操作进行优化:
浏览器会维护一个队列,把所有引起回流和重绘的操作放入队列中,如果队列中的任务数量或者时间间隔达到一个阈值,浏览器就会将队列清空,进行一次批处理,这样可以把多次回流和重绘变成一次。
当你访问以下属性或方法时,浏览器会立刻清空队列:
clientWidth、clientHeight、clientTop、clientLeftoffsetWidth、offsetHeight、offsetTop、offsetLeftscrollWidth、scrollHeight、scrollTop、scrollLeftwidth、heightgetComputedStyle()getBoundingClientRect()
因为队列中可能会有影响到这些属性或方法返回值的操作,即使你希望获取的信息与队列中操作引发的改变无关,浏览器也会强行清空队列,确保你拿到的值时最精确的。
如何避免?
CSS
- 避免使用
table布局 - 尽可能在
DOM树的最末端改变class - 避免设置多层内联样式
- 将动画效果应用到
position属性为absolute或fixed的元素上 - 避免使用
css表达式(例如:calc())
JavaScript
- 避免频繁操作样式,最好一次性重写
style属性,或者将样式列表定义为class并一次性更改class属性 - 避免频繁操作 DOM,创建一个
documentFragment,在它上面应用所有 DOM 操作,最后再把它添加到文档中(document.createDocumentFragment()) - 也可以先为元素设置
display: none,操作结束后再把它显示出来。因为在display属性为none的元素上进行的 DOM 操作不会引发回流和重绘 - 避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来
- 对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流
浏览器的渲染渲染过程与原理
跨域
安全
登录鉴权
有关OAuth看这两篇文章:OAuth 2.0 的一个简单解释、OAuth 2.0 的四种方式
Chrome DevTool Network 中的那两条红蓝线代表什么
蓝线是 DOMContentLoaded 事件触发的时间
红线是 Load 事件触发的时间
OSI 七层模型及作用
🔎猛戳我
物理层:利用传输介质为数据链路层提供物理连接,实现比特流的透明传输。
数据链路层:通过各种控制协议,将有差错的物理信道变为无差错的、能可靠传输数据帧的数据链路。
网络层:通过路由选择算法,为报文或分组通过通信子网选择最适当的路径。
传输层:向用户提供可靠的端到端的差错和流量控制,保证报文的正确传输。
会话层:组织和协调两个会话进程之间的通信,并对数据交换进行管理。
表示层:处理用户信息的表示问题,如编码、数据格式转换和加密解密。
应用层:是计算机用户,以及各种应用程序和网络之间的接口,其功能是直接向用户提供服务,完成用户希望在网络上完成的各种工作。
DNS 解析过程
首先了解三个概念:根DNS服务器、顶级域名DNS服务器和权威DNS服务器。
根DNS服务器:返回顶级域名 DNS 服务器的 IP 地址顶级域DNS服务器:返回权威域名 DNS 服务器的 IP 地址权威DNS服务器:返回相应主机的 IP 地址
DNS 解析流程如下:
- 浏览器在访问一个域名之前,比如
www.163.com,就会问本地DNS服务器这个域名的IP是什么。如果是通过DHCP 配置,本地的DNS服务器由网络服务商提供。 - 本地DNS收到来自客户端的请求。你可以想像这台服务器上缓存了一张域名与之对应IP地址的大表格。本地的DNS服务器如果缓存了这个域名的IP就直接返回,如果没有,就会问根域名服务器。根域名服务器是最高层次的,全球共有13台。它不直接用于域名解析,但能指明一条道路。
- 根DNS收到来自本地DNS的请求,发现后缀是
.com,说这个域名是由.com区域管理,我给你它的顶级域名服务器的地址,你去问问它吧。 - 本地DNS转向问顶级域名服务器,顶级域名服务器就是大名鼎鼎的一级域名,它负责管理二级域名,比如
163.com,所以它能提供一条更清晰的方向。 - 顶级域名服务器说:我给你负责
www.163.com区域的权威DNS服务器的地址,你去问它应该能问到。 - 本地DNS转向问权威DNS服务器,
163.com的权威DNS服务器是域名解析结果的原出处。 - 权威DNS服务器查询后将对应的IP地址告诉本地DNS。
- 本地DNS再将IP地址返回给客户端,客户端和目标建立连接。
三次握手的过程
- 客户端发送一个携带SYN标志位的包,请求建立连接
- 服务器响应一个携带SYN和ACK标志位的包,同意建立连接
- 客户端再发送一个携带ACK标志位的包,表示连接成功,开始进行数据传输
四次挥手过程
- 客户端发送一个携带FIN标志位的包,请求断开连接
- 服务器响应一个携带ACK标志位的包,同意客户端断开连接
- 服务器再发送一个携带FIN标志位的包,请求断开连接
- 客户端最后发送一个携带ACK标志位的包,同意服务器断开连接
TCP 和 UDP 有哪些区别?
- TCP是面向连接的(如打电话前要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接
- TCP提供可靠的服务,无差错、不丢失、不重复且按序到达;UDP尽最大努力交付
- TCP面向字节流,把数据看成一连串无结构的字节流;UDP是面向报文的,UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用)
- 每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
HTTP 首部
请求报文

- 请求行
- 请求方法
- 请求URL
- HTTP协议及版本
- 请求头
- 用来说明服务器要使用的附加信息(一些键值对),服务器借此获取客户端的信息
- 例如:User-Agent、Accept、Content-Type、Connection等
- 空行
- 分割请求头与请求体
- 请求体
- 它是将一个页面表单中的组件值通过param1=value1¶m2=value2的键值对形式编码成一个格式化串,它承载多个请求参数的数据。不但报文体可以传递请求参数,请求URL也可以通过类似于
/chapter15/user.html? param1=value1¶m2=value2的方式传递请求参数。
- 它是将一个页面表单中的组件值通过param1=value1¶m2=value2的键值对形式编码成一个格式化串,它承载多个请求参数的数据。不但报文体可以传递请求参数,请求URL也可以通过类似于
响应报文

- 响应行
- 报文协议及版本
- 状态码及状态描述
- 响应头
- 说明客户端要使用的一些附加信息
- 如:Content-Type、charset、响应的时间
- 响应体
- 返回给客户端的文本信息
HTTP 协议
- 持久连接:HTTP1.1提出了持久连接,只要通信两端的任意一端没有明确提出断开,就保持连接状态,以便下一次通信复用该连接,避免了重复建立和断开连接所造成的开销,加速了页面的呈现。
- 管道化:客户端能同时发送多个请求,服务器再按顺序一个接一个响应。
- 状态管理:HTTP是无状态协议,请求和响应一一对应,不会出现两个请求复用一个响应的情况。
HTTP 请求中的 keep-alive
HTTP 是基于 TCP 的,每一个 HTTP 请求都需要进行三次握手。如果一个页面对某一个域名有多个请求,就会进行频繁的建立连接和断开连接。所以HTTP 1.0 中出现了Connection: keep-alive,用于建立长连接。Keep-Alive 模式更加高效,因为避免了连接建立和释放的开销。但是,长时间的TCP连接容易导致系统资源无效占用,配置不当的keep-alive有时比重复利用连接带来的损失还更大。所以,正确设置keep-alive timeout时间非常重要。
HTTP 协议中的长短连接和长短轮询
短连接
所谓短连接,即连接只保持在数据传输过程,请求发起,请求建立,数据返回,连接关闭。它适用于一些实时数据请求,配合轮询来进行新旧数据的更替。
长连接
长连接便是在连接发起后,在请求关闭连接前客户端与服务器都保持连接,实质是保持这个通信管道,之后便可以对其进行复用。
短轮询
短轮询指的是在循环周期内,不断发起请求,每一次请求都立即返回结果,根据新旧数据对比决定是否使用这个结果。
长轮询
长轮询是在请求的过程中,若是服务器端数据并没有更新,那么则将这个连接挂起,直到服务器推送新的数据,再返回,然后再进入循环周期。
长短连接和长短轮询的区别
决定方式。一个TCP连接是否为长连接,是通过设置HTTP的Connection Header来决定的,而且是需要两边都设置才有效。而一种轮询方式是否为长轮询,是根据服务器端的处理方式来决定的,与客户端没有关系。
实现方式。连接的长短是通过协议来规定和实现的。而轮询的长短,是服务器通过编程的方式手动挂起请求来实现的。
HTTP 为什么不安全?
- 数据以明文传递,有被窃听的风险
- 接收到的报文无法证明是发送时的报文,不能保证完整性,因此报文有被篡改的风险
- 不验证通信两端的身份,请求或响应有被伪造的风险
HTTP 和 HTTPS 的区别
- HTTPS协议需要CA申请证书,一般免费证书比较少,因而需要一定费用
- HTTP是超文本传输协议,信息是明文传输,HTTPS则是具有安全性的SSL加密传输协议
- HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443
- HTTP的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比HTTP协议安全
HTTPS
在介绍 HTTPS 之前,先引入两个概念:对称加密和非对称加密。
对称加密:对称加密在加密和解密的过程中只使用一个密钥,这个密钥叫对称密钥,也叫共享密钥。非对称加密:非对称加密在加密的过程中使用公开密钥,在解密的过程中使用私有密钥。
HTTPS 采用混合加密机制,将两种加密算法组合使用,充分利用各自的优点。在交换共享密钥阶段使用非对称加密,在传输报文阶段使用对称加密。
HTTPS 解决的问题
HTTPS 很好的解决了 HTTP 的三个缺点(被窃听、被篡改、被伪造),HTTPS 不是一种新的协议,它是 HTTP + SSL 的结合体。
SSL(Secure Sockets Layer,安全套接层) 及其继任者 TLS(Transport Layer Security,传输层安全) 是为网络通信提供安全及数据完整性的一种安全协议。TLS 与 SSL 在传输层对网络连接进行加密。
HTTPS 改变了通信方式,它由以前的 HTTP => TCP,改为 HTTP => SSL => TCP。
防监听
数据是加密的,所以监听到的数据是密文。
防伪装
伪装分客户端伪装和服务器伪装,通信双方携带证书,证书相当于身份证,由第三方颁布,很难伪造。
防纂改
HTTPS 对数据做了摘要,篡改数据会被感知到。
HTTPS 连接建立过程
服务器端需要认证的通信过程
- 客户端发送请求到服务器
- 服务器返回证书和公钥,公钥作为证书的一部分而存在
- 客户端验证证书和公钥的有效性,如果有效,则生成共享密钥并使用公钥加密发送到服务器
- 服务器使用私钥解密数据,并使用收到的共享密钥加密数据,发送到客户端
- 客户端使用共享密钥解密数据
- SSL 加密建立
客户端认证的通信过程
客户端需要认证的过程跟服务器需要认证的过程基本相同,并且少了最开始的两步。这种情况都是证书存储在客户端,并且应用场景比较少,一般金融才用,比如支付宝、银行客户端都需安装证书。
HTTPS 有哪些缺点?
通信两端都需要进行加密和解密,会消耗大量的CPU、内存等资源,增加了服务器的负载
加密运算和多次握手降低了访问速度
在开发阶段,加大了页面调试难度。由于信息都被加密了,所以用代理工具的话,需要先解密然后才能看到真实信息
用HTTPS访问的页面,页面内的外部资源都得用HTTPS请求,包括脚本中的AJAX请求
HTTPS 的单向认证和双向认证
单向认证
客户端保存着服务器的证书并信任该证书
https一般是单向认证,这样可以让绝大部分人都可以访问你的站点
双向认证
先决条件是有2个或者2个以上的证书,一个服务器证书,其它是客户端证书
服务器保存着客户端的证书并信任该证书,客户端保存着服务器的证书并信任该证书。这样,在证书验证成功的情况下即可完成请求响应
双向认证一般用于企业应用对接
HTTP/1.1 的不足
在传输中会出现队首阻塞问题
响应不分轻重缓急,只会按先来后到的顺序执行
并行通信需要建立多个TCP连接
服务器不能主动推送客户端想要的资源,只能被动地等待客户端发起请求
由于HTTP是无状态的,所以每次请求和响应都会携带大量冗余信息
HTTP/2.0 新特性
- 二进制分帧层:是HTTP/2.0性能增强的关键,它改变了通信两端交互数据的方式,原先是以文本传输,现在要先对数据进行二进制编码,再把数据分成一个一个的帧,接着把帧送到数据流中,最后对方接受帧并拼接成一条消息,再处理请求
- 多路复用:即连接共享,即每一个request都是用作连接共享机制的。一个request对应一个id,这样一个链接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的id将request再归属到各自不同的服务器端请求里面
- 首部压缩:如上文所言。前面提到过的HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小
- 服务器推送:HTTP2.0支持服务器主动推送,简单地说就是一次请求返回多个响应,这也是一减少HTTP请求的方法。服务器除了处理最初的请求外,还会额外推送客户端想要的资源,无需客户端发出明确的请求。
HTTP2.0的多路复用是为了解决HTTP1.1两个性能问题:串行的文件传输和连接数过多。
在HTTP1.1的协议中,我们传输的request和response都是基于文本的,这样就会引发一个问题:所有的数据必须按顺序传输,比如需要传输:hello world,只能从h到d一个一个的传输,不能并行传输,因为接收端并不知道这些字符的顺序,所以并行传输在HTTP1.1是不能实现的。
HTTP2.0引入了二进制数据帧和流的概念,其中帧对数据进行顺序标识,如下图所示,这样浏览器收到数据之后,就可以按照序列对数据进行合并,而不会出现合并后数据错乱的情况。同样是因为有了序列,服务器就可以并行传输数据,这就是流所做的事情。
HTTP2.0对同一域名下所有请求都是基于流的,也就是说同一域名不管访问多少文件,也只建立一路连接。同样Apache的最大连接数为300,因为有了这个新特性,最大的并发就可以提升到300,比原来提升了6倍。
HTTP和WebSocket的区别
HTTP协议是单向协议,即浏览器只有向服务器请求资源,服务器才能将数据传送给浏览器,而服务器不能主动地向浏览器传递数据。
WebSocket是双向通信协议。解决客户端发起多个HTTP请求到服务器,浏览器必须经过长时间的轮询问题,它实现了多路复用,是全双工通信。在WebSocket协议下客户端和服务器可以同时发送信息。
301 和 302 状态码的区别
301是永久性重定向,302是暂时性重定向。
301表示旧地址A的资源已经被永久地移除了,搜索引擎在抓取新内容的同时也将旧的网址改变为重定向之后的网站。302表示旧地址A的资源还在(仍然可以访问),这个重定向只是临时地从旧地址A跳转到地址B,搜索引擎会抓取新的内容而保存旧的网址。
304 (Not Modified)状态码
当用户第一次请求资源A时,服务器会添加一个名为Last-Modified响应头,这个头说明了A的最后修改时间,浏览器会把A的内容以及最后的响应时间缓存下来,当用户第二次请求A时,在请求中包含一个名为If-Modified-Since请求头,它的值就是第一次请求时服务器通过Last-Modified响应头发送给浏览器的值,即资源A最后的修改时间。
If-Modified-Since请求头就是在告诉浏览器,我这里浏览器缓存的A最后修改时间是这个,你看看现在A最后修改时间是不是这个,如果还是,那么就不用响应这个请求了,我会把缓存里的内容直接显示出来。而服务器会获取If-Modified-Since值,与A当前的最后修改时间作对比,如果相同,则服务器返回304状态码,表示A与浏览器上次缓存的相同,无需再次发送,浏览器可以显示自己的缓存页面,如果比对不同,那么说明A已经改变,服务器会返回200状态码。
断点续传原理
HTTP1.1协议中定义了断点续传相关的HTTP头Range和Content-Range字段,实现过程如下:
客户端下载一个1024K的文件,已经下载了其中512K
网络中断,客户端请求续传,因此需要在HTTP头中声明本次需要续传的片段:
Range:bytes=512000-。这个头通知服务器端从文件的512K位置开始传输文件服务器端收到断点续传请求,从文件的512K位置开始传输,并且在HTTP头中增加:
Content-Range:bytes 512000-/1024000。并且此时服务器端返回的HTTP状态码应该是206,而不是200。
但在实际场景中,会出现一种情况,即在终端发起续传请求时,URL对应的文件内容在服务器端已经发生了变化,此时续传的数据肯定是错误的。为了解决这个问题,需要有一个标示文件唯一性的方法,比如实现Last-Midified来标识文件的最后修改时间,或者使用ETag头来放置文件的唯一标识。
另外RFC2616中同时定义有一个If-Range头,终端如果在续传时使用If-Range,If-Range中的内容可以为最初收到Etag头或者是Last-Modified中的最后修改时间。服务器在收到续传请求时,通过If-Range中的内容进行校验,校验一致时返回206的续传回应,不一致时服务器则返回200回应,回应内容为新的文件的全部数据。
206(Partial Content) 状态码
206 代表的意思就是响应了部分内容 ,那肯定就需要有一些消息头来控制怎么通过每次的大部分内容来完成整个的接收。利用的场景也就是对大文件下载比较多,也就实现了断点续传的功能。
readyState 0-4分别表示什么?
0(UNSENT):初始化,XMLHttpRequest 对象还没有完成初始化(还没有调用send()方法)1(OPENED):载入,XMLHttpRequest 对象开始发送请求(已调用send()方法,正在发送请求)2(HEADERS_RECEIVED):载入完成,XMLHttpRequest 对象的请求发送完成(send()方法执行完成,已经接收到全部响应内容)3(LOADING):解析,XMLHttpRequest 对象开始读取服务器的响应(正在解析响应内容)4(DONE):数据传输已完成或传输过程中出现问题(响应内容解析完成,可以在客户端调用了)
| 状态码 | 含义 |
|---|---|
| 100(Continue) | 继续。客户端应继续其请求 |
| 200(OK) | 一切正常。一般用于GET和POST请求 |
| 401(Unauthorized) | 请求要求用户的身份认证 |
| 403(Forbidden) | 除非拥有授权否则服务器拒绝提供所请求的资源 |
| 404(Not Found) | 告诉客户端所给的地址无法找到任何资源 |
| 500(Internal Server Error) | 服务器错误 |
| 503(Service Unavailable) | 表示服务器由于在维护或已经超载而无法响应 |
路由器工作在网络模型中那一层?为什么?
网络层。路由器是连接因特网中各局域网、广域网的设备,它会根据信道的情况自动选择和设定路由,以最佳路径,先后顺序发送信号。路由和交换机最主要的区别就是交换机发生在OSI参考模型第二层(数据链路层),而路由发生在第三层(网络层)。这一区别决定了路由和交换机在移动信息的过程中需要使用不同的控制信息,所以两者实现各自功能的方式是不同的。
介绍一下你对浏览器内核的理解?
主要分成两部分:渲染引擎和JS引擎
渲染引擎:负责取得网页的内容(HTML、XML、图像等等)、整理讯息(例如加入CSS等),以及计算网页的显示方式,然后会输出至显示器或打印机。浏览器的内核的不同对于网页的语法解释会有不同,所以渲染的效果也不相同。所有网页浏览器、电子邮件客户端以及其他需要编辑、显示网络内容的应用程序都需要内核。
JS引擎:解析和执行JavaScript来实现网页的动态效果。
最开始渲染引擎和JS引擎并没有区分的很明确,后来JS引擎越来越独立,内核就倾向于只指渲染引擎。
谈谈垃圾回收机制和内存管理
垃圾回收(Garbage Collection),简称GC。简单来讲,GC就是把内存中不需要的数据释放了,这样这部分内存就可以存放其他东西了。在JavaScript中,如果一个对象不再被引用,那么这个对象就会被GC回收。具体回收策略包括以下3种:
标记清除
当从window节点遍历DOM树不能遍历到某个对象,那么这个对象就会被标记为没用的对象。由于回收机制是周期性执行的,这样,当下一个回收周期到来时,这个对象对应的内存就会被释放。
引用计数
当系统中定义了一个对象后,对于这一块内存,JavaScript会记录有多少个引用指向这部分内存,如果这个数为零,则这部分内存会在下一个回收周期被释放。
手动释放
什么是Service Worker?
详参这篇文章
Service Worker 是独立于当前页面的一段运行在浏览器后台进程里的脚本。
Service Worker 不需要用户打开web页面,也不需要其他交互,异步地运行在一个完全独立的上下文环境,不会对主线程造成阻塞。基于Service Worker可以实现消息推送,静默更新以及地理围栏等服务。
Service Worker 提供一种渐进增强的特性,使用特性检测来渐渐增强,不会在老旧的不支持Service Worker的浏览器中产生影响。可以通过Service Worker解决让应用程序能够离线工作,让存储数据在离线时使用的问题。
基本架构
通常遵循以下基本步骤来使用service worker:
service worker URL通过
serviceWorkerContainer.register()来获取和注册。如果注册成功,service worker就在
ServiceWorkerGlobalScope环境中运行;这是一个特殊类型的worker上下文运行环境,与主运行线程相独立,同时也没有访问DOM的能力。service worker现在可以处理事件了。
受service worker控制的页面打开后会尝试去安装service worker。最先发送给service worker的事件是安装事件(在这个事件里可以开始进行填充IndexDB和缓存站点资源)。这个流程同原生App或者Firefox OS App是一样的——让所有资源可离线访问。
当
oninstall事件的处理程序执行完毕后,可以认为service worker安装完成了。下一步是激活。当service worker安装完成后,会接收到一个激活事件(active event)。
onactivate主要用途是清理先前版本的service worker脚本中使用的资源。service worker现在可以控制页面了,但仅是在
register成功后的打开的页面。也就是说,页面起始于有没有service worker,且在页面的接下来生命周期内维持这个状态。所以,页面不得不重新加载以让service worker获得完全的控制。

下面展示了service worker所支持的事件:

域名发散与域名收敛
域名发散
PC时代为了突破浏览器的的域名并发限制,遵循这样一条定律:http静态资源采用多个子域名。目的是充分利用现代浏览器的多线程并发下载能力。由于浏览器的限制,每个浏览器,允许对每个域名的连接数一般是有上限的,如下图:
上图展示了各浏览器的并行连接数(同域名),可以看到在一些浏览器内每个hostname的最大连接数基本都是6个。
所以PC时代对静态资源优化时,通常将静态资源分布在几个不同域,保证资源最完美地分域名存储,以提供最大并行度,让客户端加载静态资源更为迅速。
为什么浏览器要做并发限制呢?
- 究其根本原因,在以前,服务器端的负载能力差,稍微流量大一点服务器就容易崩溃。所以为了保护服务器不被强暴到崩溃,浏览器要对最大并发数进行限制。如果每个用户的最大并发数不限制的话,服务器的负载能力会大幅下降。
- 另外还有一个方面就是,防止分布式拒绝服务攻击(distributed denial-of-service attack,简称DDoS攻击),最基本的DDoS攻击就是利用合理的服务请求来占用过多的服务资源,从而使合法用户无法得到服务的响应。
当然,由于建立新的请求需要一定的代价,因此需要在域名发散和域名收敛之间做权衡,通常发散的域名个数为2-4个。
域名收敛
域名收敛是将静态资源只放在一个域名下面,而非发散情况下的多个域名下。域名发散可以突破浏览器的域名并发限制,那么为什么要反其道而行之呢?因为因地制宜,不同情况区别对待,域名发散是PC时代的产物,而现在进入移动互联网时代,通过无线设备访问网站,APP的用户已占据了很大一部分比例,而域名发散正是在这种情况下提出的。
通常DNS是一个开销较大的操作,而移动端由于网络带宽和实时性、资源等的限制,这些开销对移动端的用户体验是致命的,因此需要进行域名收敛。
