浏览器相关(持续更新)

151 阅读17分钟

秋招后的一些记录,看了很多东西想写下来,希望自己可以随时的查看,也希望有错误的地方大神可以指正。

1、浏览器的主要组成部分

用户界面、浏览器引擎、呈现引擎、网络、用户界面后端、JavaScript解释器、数据存储。

2、本地存储

1、cookie简单介绍

cookie一般被问简单的介绍,然后cookie的设置、读取以及是否自动携带的问题。通常在多页面中会被询问怎么进行数据分享,cookie的降域是一种。接下来详细介绍这些相关的东西。

简单介绍

开始设计是为了解决HTTP在状态管理上的不足(HTTP协议是无状态的协议)。

内部以键值对的方式存储。

向同一个域名下发送请求,都会携带相同的Cookie。

服务器拿到Cookie进行解析,便拿到了客户端的状态。

作用

可以用来做状态存储

缺点

1、容量缺陷:4KB。

2、性能缺陷:Cookie紧跟域名,不管域名下某个地址需不需要Cookie,请求都会携带上完整的Cookie。

3、安全缺陷:由于Cookie以纯文本的形式在浏览器和服务器中传递,很容易被非法用户截取,然后进行篡改。另外,在HTTPOnly为false的情况下,Cookie信息只能通过JS脚本来读取。

2、cookie属性

name属性简单介绍

一个域名下绑定的cookie,name不能相同,相同的name的值会被覆盖掉。

value属性简单介绍

cookie的Name属性和Value属性都不允许有逗号,分号,空格的存在,因此如果有着三种形式的符号存在的话,需要将其进行编码。

domain属性简单介绍(降域)

这个是指的域名,这个代表的是,cookie绑定的域名。

如果没有设置,就会自动绑定到执行语句的当前域,还有值得注意的点,统一个域名下的二级域名也是不可以交换使用cookie的。

例如:你设置www.baidu.com和image.baidu.com,依旧是不能公用的

A网页是w1.example.com/a.html,B网页是…

降域操作:

document.domain = 'example.com';

多页面共享数据的时候可以考虑降域的操作进行共享数据。

path属性

path这个属性默认是'/',这个值匹配的是web的路由。

3、cookie的有效期

介绍

如果你想要cookie存在一段时间,那么你可以通过设置Expires属性为未来的一个时间节点(Expires/Cache-control)。

1、Max-Age为正数时,cookie会在Max-Age秒之后,被删除。

2、当Max-Age为负数时,表示的是临时储存,不会生出cookie文件,只会存在浏览器内存中,且只会在打开的浏览器窗口或者子窗口有效,一旦浏览器关闭,cookie就会消失(为负数时,浏览器关闭就失效)。

3、当Max-Age为0时,又会发生什么呢,删除cookie,因为cookie机制本身没有设置删除cookie,失效的cookie会被浏览器自动从内存中删除,所以,它实现的就是让cookie失效(为0时,实现了让cookie失效)。

设置

1、 使用Cookie的: Expires 属性. 它可以设置cookie的过期时间.。

2、使用Cookie的: Max-Age 属性. 它可以指定从现在开始Cookie存在的秒数. 秒数过完则cookie过期。

Set-Cookie: id=xxxxxx; Max-Age=86400

注意:

1、Expires设置的过期时间是UTC格式, 可以用 Date.prototype.toUTCString()转换。

2、Expires设置的时间是以浏览器本地时间作为参照的, 这样同一条cookie在不同设备上的失效时间其实是不一样的。

3、如果一条cookie既没有设置Expires 也没有设置 Max-Age, 则这条cookie变成了session cookie, 这时cookie的行为和session的类似。

4、如果同时存在 Expires 和 Max-Age, 则优先以Max-Age设置的值为准。

4、其他cookie相关

secure

1、这个属性译为安全。

2、当这个属性设置为true时,此cookie只会在https和ssl等安全协议下传输。

3、这个属性并不能对客户端的cookie进行加密,不能保证绝对的安全性。

HttpOnly

如果这个属性设置为true,就不能通过js脚本来获取cookie的值。

关于js操作cookie

//读取浏览器中的cookie
console.log(document.cookie);
//写入cookie
document.cookie='myname=laihuamin;path=/;domain=.baidu.com';

5、localStorage

1、同一域名下会存储相同的一段LocalStorage。

2、容量:5M(针对一个域名,同一个域名是持久存储的)。

3、只存在客户端,默认不参与服务端的通信。

4、接口封装。通过localStorage暴露在全局,并通过setItem和getItem等方法进行操作,方便。

5、存储的都是字符串,如果存储对象需要JSON.stringify()。解析用JSON.parse()。

6、sessionStorage

1、容量:5M。

2、只存在客户端,不参与服务端通信。

3、接口封装,除了名字其他和localStorage一样。

4、会话级别的存储,并不是持久化的,会话结束(页面关闭),这部分sessionStorage就不存在了。

7、indexedDB

1、运行在浏览器中的:非关系型数据库。

2、键值对存储。

3、异步操作。数据库的读写属于I/O操作,浏览器对异步I/O提供了支持。

4、受同源策略的限制,无法访问跨域的数据库。

8、总结

1、cookie并不适合存储,而且存在非常多的缺陷。

2、localStorage和sessionStorage,默认不会参与和服务器的通信。

3、indexedDB为运行在浏览器上的非关系型数据库,为大型数据的存储提供了接口。

3、从输入URL到页面呈现发生了什么

发生三大过程分别是:网络、解析、渲染。接下来详细从这三方面介绍。

网络

网络请求阶段

1、构建请求

2、查找强缓存

命中就直接使用,否则进入下一步。

3、DNS解析

DNS(域名系统),得到具体IP的过程就是DNS解析,不指定端口默认80端口

(详细会在计算机网络篇中介绍)

4、建立TCP连接

Chrom在同一域名下要求同时最多6个TCP连接。

什么是TCP:传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议。

简历TCP连接经历了下面三个阶段:

一、通过三次握手建立连接

二、进行数据传输:

数据包校验:接收方收到数据包后必须向发送方发送确认,如果发送方没有收到,就判断数据包丢失,并重新发送数据包。

优化策略:把大的数据包拆成一个个小包,依次传输到接收方,接收方组装成完整数据包。

三、断开连接,四次挥手。

(详细会在计算机网络篇中介绍)

5、发送HTTP请求

请求头、请求行、请求体

(详细会在计算机网络篇中介绍)

网络响应阶段

1、HTTP请求到达服务器,服务器进行对应的处理。最后要把数据传给浏览器,也就是返回网络响应。

2、响应行类似下面这样:

HTTP/1.1 200 OK

3、响应完了就要判断Connection字段如果为keep-alive表示建立了持久连接,这样TCP会一直保持,否则断开TCP连接,请求-响应流程结束。

解析

完成了网络请求和响应,如果响应头中Content-Type的值是text/html。那么接下来就是解析和渲染工作了。

构建DOM树

HTML文法本质

解析算法:1、标记化(词法分析)2、建树(语法分析)3、容错机制

样式计算

来源:1、link标签引用。2、style标签中的样式。3、元素的内嵌style属性。

1、格式化样式表:渲染器引擎接收到CSS文本之后旧将其转化为一个结构化对象,即:styleSheets。

2、标准化样式属性:有些数值并不容易被理解,在这里计算样式之前进行标准化。

3、计算每个节点的具体样式。

生成布局树

1、浏览器的布局系统确定元素的位置,也就是要生成一棵布局树(Layout Tree)。

2、遍历生成的 DOM 树节点,并把他们添加到布局树中。

3、计算布局树节点的坐标位置。

渲染

渲染阶段有四个方面:建图层树、生成绘制列表、生成图块并栅格化、显示器显示内容

4、从请求一个url到请求响应和页面渲染,有哪些可以做到性能优化的工作(优化)

减少请求次数方面

1、减少DNS路由查找。

**2、使用长连接或管道连接:**使用keep-alive或presistent来建立持久连接,持久连接降低了时延和连接建立的开销。管道化连接在HTTP2协议中可以开启管道化连接,即单条连接的多路复用。

3、使用CDN:(1)CDN(contentdistribute network,内容分发网络)的本质是一个缓存。

(2)将数据缓存在离用户最近的地方,使用户以最快速度获取数据,即所谓网络访问第一跳。

(3)由于CDN部署在网络运营商的机房,这些运营商又是终端用户的网络服务提供商,因此用户请求路由的第一跳就到达了CDN服务器,当CDN节点中存在浏览器请求的资源时,从CDN节点直接返回给浏览器,最短路径返回响应,加快用户访问速度,减少数据中心负载压力。

(4)如果该节点中请求的文件不存在,就会向目标站获取这个文件,然后返回给用户。

(5)CDN缓存的一般是静态资源,如图片、文件、CSS、script脚本、静态网页。

**4、浏览器强缓存:**通过设置http头中的cache-control和expires的属性,可设定浏览器缓存,缓存时间可以是数天,甚至是几个月。

**5、避免重定向:**重定向之所以会比较慢,是因为它重复了域名查找,tcp链接,发送请求。

**6、资源合并:**合并CSS、合并javascript、合并图片。

**7、CSS使用雪碧图:**一次性获取所有图像到本地,不需要每次遇到图片就发出请求。

**8、采用懒加载:**不会在第一次渲染页面的时候一次性请求所有的外部资源(图片一类)。只显示用户所能看到屏幕内的内容。

减少请求资源大小方面

**1、cookie优化:**减少cookie传输/减少本地cookie存储内容的大小 。

**2、将请求到的资源压缩:**在服务器端对文件进行压缩,在浏览器端对文件解压缩,可有效减少通信传输的数据量。

渲染阶段的优化

1、优化资源加载:

(1)资源加载的位置:

​ 1、CSS放在HTML的上部,确保正常的渲染过程。浏览器有可能还未下载和解析到 CSS就已经开始渲染页面从而导致了页面呈现空白或者无格式的文本状态,用户体验差。

​ 2、JS放在HTML的下部。目的是防止阻塞 HTML 和 CSS 元素的加载过程。

(2)资源加载时机:

​ 1、采用异步脚本加载:

<script src="example.js" async / defer></script>

​ defer: 异步加载,在HTML解析完成后执行。defer的实际效果与将代码放在body底部类似。

​ async: 异步加载,加载完成后立即执行。

​ 2、资源懒加载和预加载

2、关于DOM优化:

(1)缓存DOM。

(2)减少DOM深度及DOM数量.

(3)避免频繁操作DOM。(主要是为了减少重绘和回流(重绘回流在后面介绍))

3、关于JS:

(1)采用事件委托。

(2)防抖和节流(在后面介绍)。

4、关于CSS:

引入CSS外部样式表,尽可能使用link属性,减少使用 @import 指令。

因为@import是同步操作,只有把对应的样式导入后,才会继续向下执行,而link是异步的操作。

5、浏览器是如何渲染UI的

1、浏览器获取HTML文件,然后对文件进行解析,形成DOM Tree。

2、与此同时,进行CSS解析,生成Style Rules。

3、接着将DOM Tree 与Style Rules合成Render Tree。

4、接着进入布局(Layout)阶段,也就是为每个节点分配一个应出现在屏幕上的确切坐标。

5、随后调用GPU进行绘制(Paint),遍历Render Tree的节点,并将元素呈现出来。

6、浏览器如何解析css选择器

1、浏览器会『从右往左』解析CSS选择器。

2、DOM Tree与Style Rules合成为 Render Tree,实际上是将Style Rules附着到DOM Tree 上。

3、此需要根据选择器提供的信息对DOM Tree进行遍历,才能将样式附着到对应的DOM元素上。

7、DOM Tree是如何构建的

1、转码:浏览器将接收到的二进制数据按照指定编码格式转化为HTML字符串。

2、生成Tokens:之后开始parser,浏览器会将HTML字符串解析成Tokens。

3、构建Nodes:对Node添加特定的属性,通过指针确定 Node 的父、子、兄弟关系和所属 treeScope。

4、生成DOM Tree:通过node包含的指针确定的关系构建出DOM Tree。

8、前端如何实现即时通讯

1、短轮询

短轮询的原理很简单,每隔一段时间客户端就发出一个请求,去获取服务器最新的数据,一定程度上模拟实现了即时通讯。

优点:兼容性强,实现非常简单。

缺点:延迟性高,非常消耗请求资源,影响性能。

2、comet

1、一种是基于 AJAX 的长轮询(long-polling)方式

优点:兼容性好,资源浪费较小。

缺点:服务器hold连接会消耗资源,返回数据顺序无保证,难于管理维护。

2、另一种是基于 Iframe 及 htmlfile 的流(streaming)方式,通常被叫做长连接。

优点:兼容性好,消息即时到达,不发无用请求。

缺点:服务器维护长连接消耗资源。

3、SSE

Server-Sent Event,服务端推送事件。是一种允许服务端向客户端推送新数据的HTML5技术。

优点:基于HTTP而生,因此不需要太多改造就能使用,使用方便,而websocket非常复杂,必须借助成熟的库或框架。

缺点:基于文本传输效率没有websocket高,不是严格的双向通信,客户端向服务端发送请求无法复用之前的连接,需要重新发出独立的请求。

4、Websocket

Websocket是一个全新的、独立的协议,基于TCP协议,与http协议兼容、却不会融入http协议,仅仅作为html5的一部分,其作用就是在服务器和客户端之间建立实时的双向通信。

优点:真正意义上的实时双向通信,性能好,低延迟。

缺点:独立与http的协议,因此需要额外的项目改造,使用复杂度高,必须引入成熟的库,无法兼容低版本浏览器。

5、Web Worker

Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。

6、Service workers

Service workers 本质上充当Web应用程序与浏览器之间的代理服务器,也可以在网络可用时作为浏览器和网络间的代理,创建有效的离线体验。

9、什么是浏览器的同源策略

这是一个用于隔离潜在恶意文件的重要安全机制。

同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。

是以下三个标签可以不受限制:
<img src=XXX>
<link href=XXX>
<script src=XXX>

10、跨域

1、jsonp

jsonp的具体实现请看 前端相关实现篇

优点:1、实现简单。2、兼容性非常好

缺点:1、只支持get请求(因为

2、cors

配置:

res.header('Access-Control-Allow-Origin', 'http://example.com');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');

详细介绍:

1、浏览器发起cors简单请求

(1)具体来说,就是在头信息之中,增加一个Origin字段。

(2)只要同时满足以下两大条件,就属于简单请求。

​ 条件1:使用下列方法之一:GET、HEAD、POST。

​ 条件2:Content-Type 的值仅限于下列三者之一:text/plain、multipart/form-data、application/x-www-form-urlencoded

(3)请求中的任意 XMLHttpRequestUpload 对象均没有注册任何事件监听器; XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问。

2、浏览器发送非简单cors请求

(1)非简单请求是那种对服务器有特殊要求的请求。

(2)比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json

3、发起非简单请求有如下步骤

(1)预检请求

​ 非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。

​ 当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。

​ 只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。

​ "预检"请求用的请求方法是OPTIONS,表示这个请求是用来询问服务器支持什么请求方法的

​ Access-Control-Request-Method:该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法。

​ Access-Control-Request-Headers:该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段。

(2)浏览器的正常请求和回应

一旦服务器通过了"预检"请求,以后每次浏览器正常的CORS请求,就都跟简单请求一样。

会有一个Origin头信息字段。服务器的回应,也都会有一个Access-Control-Allow-Origin头信息字段。

4、其他:

XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。

浏览器发送CORS请求是默认不发送Cookie和HTTP认证信息。

配置:

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。

3、中间代理

一般通过nginx进行的中间代理。

nginx是一款极其强大的web服务器,其优点就是轻量级、启动快、高并发。

现在的新项目中nginx几乎是首选,我们用node或者java开发的服务通常都需要经过nginx的反向代理。

4、其他跨域方案

1、HTML5 XMLHttpRequest 有一个API,postMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。

2、WebSocket 是一种双向通信协议,在建立连接之后,WebSocket 的 server 与 client 都能主动向对方发送或接收数据,连接建立好了之后 client 与 server 之间的双向通信就与 HTTP 无关了,因此可以跨域。

3、window.name + iframe:window.name属性值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2M),我们可以利用这个特点进行跨域。

4、location.hash + iframe:a.html欲与c.html跨域相互通信,通过中间页b.html来实现。 三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。

5、document.domain + iframe: 该方式只能用于二级域名相同的情况下,比如 a.test.com 和 b.test.com 适用于该方式,我们只需要给页面添加 document.domain ='test.com' 表示二级域名都相同就可以实现跨域,两个页面都通过js强制设置document.domain为基础主域,就实现了同域。

5、附加介绍WebSocket

1、建立在 TCP 协议之上,它需要通过握手连接之后才能通信,服务器端的实现比较容易。

2、与 HTTP 协议有着良好的兼容性。默认端口也是80或443, (并且握手阶段采用 HTTP 协议)
,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。

3、WebSocket的通信建立——握手过程。WebSocket的握手使用HTTP来实现,客户端发送带有Upgrade头的HTTP Request消息。

Connection: Upgrade
Upgrade: websocket

HTTP1.1与WebSocket的异同

相同点:

(1)都是基于TCP的应用层协议。

(2)都使用Request/Response模型进行连接的建立。

(3)在连接的建立过程中对错误的处理方式相同,在这个阶段WebSocket可能返回和HTTP相同的返回码。

不同点:

(1)HTTP协议基于Request/Response,只能做单向传输,是半双工协议,而WebSocket是全双工协议,类似于Socket通信,双方都可以在任何时刻向另一方发送数据。

(2)WebSocket使用HTTP来建立连接,但是定义了一系列新的Header域,这些域在HTTP中并不会使用。换言之,二者的请求头不同。

(3)WebSocket的连接不能通过中间人来转发,它必须是一个直接连接。如果通过代理转发,一个代理要承受如此多的WebSocket连接不释放,就类似于一次DDOS攻击了。

(4)WebSocket在建立握手连接时,数据是通过HTTP协议传输的,但在建立连接之后,真正的数据传输阶段是不需要HTTP协议参与的。

(5)WebSocket传输的数据是二进制流,是以帧为单位的,HTTP传输的是明文传输,是字符串传输,WebSocket的数据帧有序。

HTTP的长连接与WebSocket的持久连接的异同

HTTP1.1的连接默认使用长连接(Persistent connection)。

“长轮询”:即客户端发送一个超时时间很长的Request,服务器保持住这个连接,在有新数据到达时返回Response。

WebSocket的持久连接:只需建立一次Request/Response消息对,之后都是TCP连接,避免了需要多次建立Request/Response消息对而产生的冗余头部信息。节省了大量流量和服务器资源。因此被广泛应用于线上WEB游戏和线上聊天室的开发。

11、常见的浏览器兼容性解决方案

1、不同浏览器的标签默认的margin和padding不同

解决方案:CSS里 *{margin:0;padding:0;}

备注:这个是最常见的也是最易解决的一个浏览器兼容性问题,几乎所有的CSS文件开头都会用通配符*来设置各个标签的内外补丁是0。

2、图片默认有间距。使用float属性为img布局

3、标签最低高度设置min-height不兼容。

如果我们要设置一个标签的最小高度200px,需要进行的设置为:{min-height:200px; height:auto !important; height:200px; overflow:visible;}。

4、块属性标签float后,又有横行的margin情况下,在IE6显示margin比设置的大。

解决方案:在float的标签样式控制中加入 display:inline;将其转化为行内属性。

5、设置较小高度标签(一般小于10px),在IE6,IE7,遨游中高度超出自己设置高度 (IE6、7和遨游里这个标签的高度不受控制,超出自己设置的高度)。

解决方案:给超出高度的标签设置overflow:hidden;或者设置行高line-height 小于你设置的高度。

6、行内属性标签,设置display:block后采用float布局,又有横行的margin的情况,IE6间距bug。

解决方案:在display:block;后面加入display:inline;display:table;

12、浏览器内多个标签页之间的通信

1、localStorage

标签页调用localStorage.setItem(name,val)保存数据localStorage.removeItem(name)删除数据的时候会触发 'storage'事件。

另外一个标签页监听document对象的storage事件,在事件event对象属性中获取信息。

window.addEventListener("storage", function(event){  
			console.log(event.key + "=" + event.newValue);  
		}); 

2、cookie

在A页面将需要传递的消息存储在cookie当中。

在B页面设置setInterval,以一定的时间间隔去读取cookie的值。

(不同域需要进行降域处理)

3、WebSocket、SharedWorker

13、浏览器同域名请求的最大并发数限制

一般限制在8个以内吧

Chrome同域名下资源加载的最大并发连接数为6

14、CDN

什么是 CDN:中文名叫做「内容分发网络」。它的作用是减少传播时延,找最近的节点。

CDN 的优点:1、访问加速。2、减轻源站(服务器)负载。3、抗住攻击。

应用:

1、最常见的应用,就是用于前端静态资源的加速

2、缓存设置: s-maxage。我们可以把 max-age 用于本地缓存,把 s-maxage 用于 CDN 缓存时间,避免脏数据的产生。

3、缓存命中率。

4、判断是否命中缓存。

5、资源预热。

6、Vary。

7、Range。

8、无私钥 HTTPS。

15、如何判断网页加载完成了

window. document.readyState == "complete"
        document.addEventListener("readystatechange", function (e) {
            if (e.target.readyState === 'complete') {
                console.log("加载完成");
            } else {
                console.log("正在加载");
            }
        })

16、懒加载和预加载

1、懒加载

懒加载也就是延迟加载。

优点:页面加载速度快、可以减轻服务器的压力、节约了流量,用户体验好。

2、预加载

预加载的核心要点如下:

1.图片等静态资源在使用之前的提前请求;

2.资源后续使用时可以从缓存中加载,提升用户体验;

3.页面展示的依赖关系维护(必需的资源加载完才可以展示页面,防止白屏等);

实现预加载主要有三个方法:

1.html中img标签最初设置为display:none;

2.js脚本中使用image对象动态创建好图片;

3.使用XMLHttpRequest对象可以更加精细的控制预加载过程,缺点是无法跨域:

提前加载图片,当用户需要查看时可直接从本地缓存中渲染。

意义:预加载可以说是牺牲服务器前端性能,换取更好的用户体验,这样可以使用户的操作得到最快的反映。

17、Session、Cookie、Token、Json Web Toekns(JWT)

1、Cookie 和 Session

2、JWT 和 Session Cookies 的相同之处

3、什么是 Session Cookies

4、JSON Web Token

5、JWT 和 Session Cookies 的不同

18、实现图片懒加载

方案一:clientHeight、scrollTop 和 offsetTop。

方案二:getBoundingClientRect。

方案三: IntersectionObserver。

19、防抖节流

这里简单阐述概念,为了第四点优化的解释。具体代码实现请看 前端相关实现篇。

1、防抖

一段时间内不论多少次点击都被忽略当持续触发某个事件时,会有规律的每隔时间n就执行一次函数(一段时间内只执行一次)。

应用:

1、鼠标不断触发单位时间内只执行一次。

2、window触发resize的时候。

2、节流

指的是在时间n内,函数被触发多次,但只执行一次新的触发。也就在时间n内,碰到新的触发,就清除之前的,重新计时(每次新的触发就重新记时)。

应用:

1、search搜索。

2、频繁点赞和取消点赞。

20、重绘和回流

重绘不一定导致回流,但回流一定会发生重绘

渲染进程中的主线程(回流会全部从新执行):生成DOM树、计算样式、生成布局树、建图层树、绘制列表

1、重绘

触发条件:当DOM的修改导致了样式的变化,并且没有影响几何属性的时候,会导致重绘。

计算样式和绘制列表(中间会跳过生成布局树和建立图层树)

2、回流(重排)

触发条件:当我们对DOM结构的修改引发DOM几何尺寸变化的时候,会发生回流的过程

(1)一个DOM元素的几何变化,常见的集合属性有width、height、padding、margin、left、top、border 。

(2)使DOM节点发生增减或者移动 。

(3)读写offset族、scroll族和client族属性的时候,浏览器为了获取这些值,需要进行回流的操作。

(4)调用window.getComputedStyle方法。

3、合成

利用CSS3的transform、opacity、filter这些属性可以实现合成的效果,也就是大家常说的GPU加速。

GPU加速的原因:在合成的情况下,会之间跳过布局和绘制流程,之间进入非主线程处理部分,即直接交给合成线程处理。

能充分发挥GPU的优势。合成线程在生成位图的过程中会调用线程池,并在其中使用GPU进行加速,而GPU是擅长处理位图数据的。

没有占用主线程的资源,即使主线程卡住了,效果依然能够流畅的展示。

4、开发注意

1、避免频繁使用style,而是采用class的方式。

2、使用createDocumentFragment进行批量的 DOM 操作。

3、对于 resize、scroll 等进行防抖/节流处理。

4、添加 will-change: tranform ,让渲染引擎为其单独实现一个图层,当这些变换发生时,仅仅只是利用合成线程去处理这些变换,而不牵扯到主线程,大大提高渲染效率。当然这个变化不限于tranform, 任何可以实现合成效果的 CSS 属性都能用will-change来声明。

5、如何避免重绘和回流

1、集中改变样式:我们往往通过改变class的方式来集中改变样式。

2、使用DocumentFragment:我们可以通过createDocumentFragment创建一个游离于DOM树之外的节点,然后在此节点上批量操作,最后插入DOM树中,因此只触发一次重排

3、提升为合成层: will-change: transform;

21、XSS攻击

1、什么是XSS攻击

XSS 全称是 Cross Site Scripting(即跨站脚本),为了和 CSS 区分,故叫它XSS。

XSS 攻击是指浏览器中执行恶意脚本(无论是跨域还是同域),从而拿到用户的信息并进行操作。

2、攻击完成的事情

(1)窃取Cookie。

(2)监听用户行为,比如输入账号密码后直接发送到黑客服务器。

(3)修改DOM伪造登陆表单。

(4)在页面生成浮窗广告。

3、XSS攻击的实现三种方式

存储型:将恶意的脚本存储起来。存储型的XSS将脚本存储到服务端的数据库,然后再客户端执行这些脚本,从而达到攻击效果。

常见的场景就是留言区提交脚本,前后端没有做好转义工作。

反射型:指的是恶意脚本作为网络请求的一部分。

比如:

http://sanyuan.com?q=<script>alert("你完蛋了")</script>

之所以叫它反射型, 是因为恶意脚本是通过作为网络请求的参数,经过服务器,然后再反射到HTML文档中,执行解析。

文档型:

文档型的 XSS 攻击并不会经过服务端,而是作为中间人的角色,在数据传输过程劫持到网络数据包,然后修改里面的 html 文档。

这样的劫持方式包括WIFI路由器劫持或者本地恶意软件等。

4、防范措施

1、无论是在前端和服务端,都要对用户的输入进行转码或者过滤。

**2、利用 CSP:**核心思想就是服务器决定浏览器加载哪些资源。

​ 核心思想就是服务器决定浏览器加载哪些资源。

​ 限制其他域下的资源加载。

​ 禁止向其它域提交数据。

​ 提供上报机制,能帮助我们及时发现 XSS 攻击。

**3、利用 HttpOnly:**很多 XSS 攻击脚本都是用来窃取Cookie, 而设置 Cookie 的 HttpOnly 属性后(为true),JavaScript 便无法读取 Cookie 的值。这样也能很好的防范 XSS 攻击。

22、CSRF攻击

1、什么是CSRF攻击

CSRF(Cross-site request forgery), 即跨站请求伪造。

指的是黑客诱导用户点击链接,打开黑客的网站,然后黑客利用用户目前的登录状态发起跨站请求

2、攻击完成的事(点击黑客连接后)

1、自动发 GET 请求。

黑客网页里面可能有一段这样的代码:

<img src="https://xxx.com/info?user=hhh&count=100">

进入页面后自动发送 get 请求,值得注意的是,这个请求会自动带上关于 xxx.com 的 cookie 信息(这里是假定你已经在 xxx.com 中登录过)。

如果服务器没有验证机制,它可能认为请求是一个正常用户。因为携带了cookie,所以就可以进行相应的操作,比如转账。

2、自动发 POST 请求。

可能是一个表单信息,同样携带cookie,让服务器误以为是一个正常的用户在操作。

3、诱导点击发送 GET 请求。

点击后,自动发送 get 请求,接下来和自动发 GET 请求部分同理。

3、防范措施

1、利用Cookie的SameSite属性

原理:

CSRF攻击中重要的一环就是自动发送目标站点下的 Cookie,Cookie 模拟了用户的身份。

在 Cookie 当中有一个关键的字段,可以对请求中 Cookie 的携带作一些限制这个字段就是SameSite。

SameSite可以设置为三个值,Strict、Lax和None。(谷歌新版本更新有这个问题2020年吧好像)。

在Strict模式下,浏览器完全禁止第三方请求携带Cookie。比如请求sanyuan.com网站只能在sanyuan.com域名当中请求才能携带 Cookie,在其他网站请求都不能。

在Lax模式,就宽松一点了,但是只能在 get 方法提交表单况或者a 标签发送 get 请求的情况下可以携带 Cookie,其他情况均不能。

在None模式下,也就是默认模式,请求会自动携带上 Cookie。

2、验证来源站点

需要要用到请求头中的两个字段: Origin和Referer。

Origin只包含域名信息,而Referer包含了具体的 URL 路径

这两者都是可以伪造的,通过 Ajax 中自定义请求头即可,安全性略差。

3、CSRF Token

浏览器向服务器发送请求时,服务器生成一个字符串,将其植入到返回的页面中。

然后浏览器如果要发送请求,就必须带上这个字符串,然后服务器来验证是否合法,如果不合法则不予响应。

4、总结对比

CSRF 攻击并不需要将恶意代码注入用户当前页面的html文档中,而是跳转到新的页面。

利用服务器的验证漏洞和用户之前的登录状态来模拟用户进行操作。