本系列持续更新…
1. 常见http status
1XX系列:指定客户端应相应的某些动作,代表请求已被接受,需要继续处理。由于 HTTP/1.0 协议中没有定义任何 1xx 状态码,所以除非在某些试验条件下,服务器禁止向此类客户端发送 1xx 响应。
2XX系列:代表请求已成功被服务器接收、理解、并接受。这系列中最常见的有200、201状态码。
3XX系列:代表需要客户端采取进一步的 *** 作才能完成请求,这些状态码用来重定向,后续的请求地址(重定向目标)在本次响应的 Location 域中指明。这系列中最常见的有301、302状态码。
4XX系列:表示请求错误。代表了客户端看起来可能发生了错误,妨碍了服务器的处理。常见有:401、404状态码。
5xx系列:代表了服务器在处理请求的过程中有错误或者异常状态发生,也有可能是服务器意识到以当前的软硬件资源无法完成对请求的处理。常见有500、503状态码。
2开头 (请求成功)表示成功处理了请求的状态代码
200 (成功ok) 服务器已成功处理了请求
201 (已创建) 请求成功并且服务器创建了新的资源
202 (已接受) 服务器已接受请求,但尚未处理
203 (非授权信息) 服务器已成功处理了请求,但返回的信息可能来自另一来源
204 (无内容) 服务器成功处理了请求,但没有返回任何内容
205 (重置内容) 服务器成功处理了请求,但没有返回任何内容
206 (部分内容) 服务器成功处理了部分 GET 请求
3开头 (请求被重定向)表示要完成请求,需要进一步 *** 作。 通常,这些状态代码用来重定向
300 (多种选择) 针对请求,服务器可执行多种 *** 作。 服务器可根据请求者 (user agent) 选择一项 *** 作,或提供 *** 作列表供请求者选择。
301 (永久移动) 请求的网页已永久移动到其他URL。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。
302 (临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
303 (查看其他位置) 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码。
304 (未修改) 表示客户端缓存的版本是最近的 。自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。
305 (使用代理) 请求者只能使用代理访问请求的网页。 如果服务器返回此响应,还表示请求者应使用代理。
307 (临时重定向)请求的文档被临时移动到别处。 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
4开头 (请求错误)这些状态代码表示请求可能出错,妨碍了服务器的处理
400 (错误请求) 服务器不理解请求的语法。
401 (未授权) 请求要求用户身份验证。 对于需要登录的网页,服务器可能返回此响应。
403 (禁止) 服务器拒绝请求。通常是权限设置所致
404 (未找到) 服务器找不到请求的网页。
405 (方法禁用) 禁用请求中指定的方法。
406 (不接受) 无法使用请求的内容特性响应请求的网页。
407 (需要代理授权) 此状态代码与 401(未授权)类似,但指定请求者应当授权使用代理。
408 (请求超时) 服务器等候请求时发生超时。
409 (冲突) 服务器在完成请求时发生冲突。 服务器必须在响应中包含有关冲突的信息。
410 (已删除) 如果请求的资源已永久删除,服务器就会返回此响应。
5开头(服务器错误)这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错
500 (服务器内部错误) 服务器遇到错误,无法完成请求。
501 (尚未实施) 服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码。
502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。
503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。
504 (网关超时) 服务器作为网关或代理,未及时从上游服务器获取请求。
505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。
跨域问题其实就是浏览器的同源策略造成的。
为什么浏览器禁止跨域
为了防止网站被恶意攻击(XSS、CSRF攻击),导致用户信息被泄露,所以浏览器使用了同源策略。
2.1 同源策略同源策略是一种约定,同源是指 “协议 + 端口 + 域名
” 三者相同,即便两个不同的域名指向同一个ip地址,也非同源。
同源策略的限制
Cookie、LocalStorage、IndexedDB 等存储性内容
DOM 节点
当前域下 ajax 无法发送跨域请求
跨域是指浏览器允许向服务器发送跨域请求,从而克服Ajax只能同源使用的限制。
跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。
跨域解决方案
JSONP跨域Node中间件代理nginx反向代理WebSocketpostMessagelocation.hash + iframewindow.name + iframedocument.domain + iframeCORS跨域资源共享CORS支持所有类型的HTTP请求,是跨域HTTP请求的根本解决方案
CORS 需要浏览器和后端同时支持,浏览器会自动进行 CORS 通信,实现 CORS 通信的关键是后端。只要服务器实现了 CORS,就实现了跨域。
浏览器内核(支持浏览器运行的最核心的程序):包括JS引擎+渲染引擎
浏览器 = 客户端
浏览器根据 DNS 服务器得到域名对应的 IP 地址向该 IP 地址发送 HTTP 请求服务器收到、处理并返回 HTTP 请求浏览器得到返回内容返回的内容其实就是一堆 HMTL 格式的字符串,因为只有 HTML 格式浏览器才能正确解析 3.2 页面渲染过程
DOM --> CSSOM --> RenderTree --> Layout --> Paint
解析HTML,生成DOM树字节数据 => 字符串 => Token => Node => DOM解析CSS,生成CSS规则树
字节数据 => 字符串 => Token => Node => CSSOM解析完成后,通过 DOM 树和 CSS 规则树 构建 Rendering Tree布局Render树(layout 重排/ reflow回流)绘制Render树 (paint)浏览器将各层信息发送给GUI,GUI将各层合成,显示在屏幕上 3.3 浏览器渲染过程(解析html)遇到JS文件
JS 的执行是在生成渲染树之前的。这也是为什么 JavaScript 的加载、解析与执行会阻塞 DOM 的构建,阻塞页面的渲染。
渲染过程中,如果遇到
就停止渲染,执行 JS 代码在构建DOM时,HTML解析器若遇到了JavaScript,那么它会暂停构建DOM,将控制权移交给JS引擎,等JS引擎运行完毕,浏览器再从中断的地方恢复DOM构建也就是说,如果你想首屏渲染的越快,就越不应该在首屏就加载 JS 文件,这也是都建议将 script 标签放在 body 标签底部的原因,若是SPA可能沒啥差別。当然并不是说 script 标签必须放在底部,因为可以给 script 标签添加 defer 或者 async 属性
3.4 什么情况阻塞渲染
渲染的前提是生成渲染树,所以 HTML 和 CSS 肯定会阻塞渲染,如果想渲染的越快,应该降低一开始需要渲染的文件大小,并且扁平层级,优化选择器JavaScript 的加载、解析与执行会阻塞 DOM 的构建,阻塞页面的渲染,不应该在首屏就加载 JS 文件,将 script 标签放在 body 标签底部,给 script 标签添加 defer 或者 async 属性
3.5 浏览器渲染优化
针对JavaScript将 js 放在页面底部位置; 尽可能用 defer 或者 async 避免阻塞的 js 加载,确保 DOM 树生成完才会去加载 JS针对CSS
导入外部样式使用link 代替 @import
如果css少,尽可能采用内嵌样式,直接写在style标签中针对DOM树、CSSOM树
降低 HTML 层级、标签尽量语义化等、降低选择器层级针对回流与重绘
不要使用table布局
dom元素position属性使用absolute或者fixed
visibility:hidden替换display:none
操作DOM时,尽量在低层级的DOM节点进行操作
避免频繁操作DOM,可以创建一个文档片段 3.5 正确性能优化思路
遇到问题应该先通过各种分析工具,找到出现性能瓶颈的原因,再根据这个原因去寻找对应的优化方式
如果是首屏加载的性能问题根据开发者工具,比如看 network 是否是由于资源体积太大导致请求慢,还是后端处理慢,还是资源太多了加载慢;如果都不是,可能是因为渲染慢
再去分析 performce 面板,看一下是 js 执行慢,还是啥原因再比如遇到了 webpack 的性能问题(比如打包的资源太大了)
通过 webpack-bundle-analyzer 插件去分析包大的原因 4. 浏览器重排重绘
重绘
不⼀定重排,重排必定重绘
布局发生了改变就会触发重排(回流),样式发生了改变就会触发重绘
一个元素的 样式/ 几何属性发生改变(例如背景色),但是没有改变布局(例如宽高); 浏览器会根据元素的新属性重新绘制,元素外观重新展示;
元素的样式发生变动 ,但是位置没有改变。此时在关键渲染路径中的 Paint 阶段
,将渲染树中的每个节点转换成屏幕上的实际像素,这一步通常称为绘制或栅格化。
当DOM变化影响了元素的几何属性,浏览器此时需要重新计算元素几何属性,并且页面中其他元素的几何属性可能会受影响这样渲染树就发生了改变,也就是重新构造渲染树。
元素的位置发生变动时发生重排,也叫回流。此时在 Layout 阶段
,重新计算每一个元素在设备视口内的确切位置和大小。当一个元素位置发生变化时,其父元素及其后边的元素位置都可能发生变化,代价极高。
重排触发条件:
1、添加或者删除可见的DOM元素;
2、元素位置改变;
3、元素尺寸改变——边距、填充、边框、宽度和高度
4、内容改变——比如文本改变或者图片大小改变而引起的计算值宽度和高度改变;
5、页面渲染初始化;
6、浏览器窗口尺寸改变——resize事件发生时
4.3 减少重绘重排浏览器自身优化(渲染队列)
浏览器会维护1个队列,把所有会引起重排,重绘的操作放入这个队列,等队列中的操作到一定数量或者到了一定时间间隔,浏览器就会flush队列,进行一批处理,这样多次重排,重绘变成一次重排重绘
批量修改DOM
不要使用Table布局
dom元素position属性使用absolute或者fixed
使用CSS3硬件加速
避免设置多层内联样式
将频繁重绘或重排的节点设置为图层
visibility:hidden替换display:none
回答总结!!!
重排和重绘是浏览器关键渲染路径上的两个节点, 浏览器的关键渲染路径就是 DOM 和 CSSOM 生成渲染树,然后根据渲染树通过一个布局(也叫 layout)步骤来确定页面上所有内容的大小和位置,确定布局后,将像素绘制 (也叫 Paint)到屏幕上。
其中重排就是当元素的位置发生变动的时候,浏览器重新执行布局这个步骤,来重新确定页面上内容的大小和位置,确定完之后就会进行重新绘制到屏幕上,所以重排一定会导致重绘。
如果元素位置没有发生变动,仅仅只是样式发生变动,这个时候浏览器重新渲染的时候会跳过布局步骤,直接进入绘制步骤,这就是重绘,所以重绘不一定会导致重排。
Cookie:最早被提出来的本地存储方式
Cookie和session结合使用,将sessionId存储到Cookie中,每次发请求都会携带这个sessionId,这样服务端就知道是谁发起的请求,从而响应相应的信息;
可以用来统计页面的点击次数
LocalStorage:HTML5新引入的特性
有些网站有换肤的功能,可以将换肤信息存储在本地的LocalStorage中,当需要换肤的时候,直接操作LocalStorage即可;
用户浏览信息也会存储在LocalStorage中,还有网站的一些不常变动的个人信息等也可以存储在本地的LocalStorage中
SessionStorage:HTML5才提出来的存储方案
SessionStorage具有时效性,可以用来存储一些网站的游客登录的信息,还有临时的浏览记录的信息。当关闭网站之后,这些信息也就随之消除了
在HTML5标准前本地储存的主要⽅式,优点是兼容性好,请求头⾃带cookie⽅便,缺点是⼤⼩只有4k,⾃动请求头加⼊cookie浪费流量localStorage
HTML5加⼊的⽅式,优点是操作⽅便,永久性储存(除⾮⼿动删除),⼤⼩为5M,兼容IE8+sessionStorage
与localStorage基本类似,区别是sessionStorage当⻚⾯关闭后会被清理,⽽且与cookie、localStorage不同,他不能在所有同源窗⼝中共享,是会话级别的储存⽅式;Web SQL
2010年被W3C废弃的本地数据库数据存储⽅案,但是主流浏览器(⽕狐除外)都已经有了相关的实现,websql类似于SQLite,是真正意义上的关系型数据库,⽤sql进⾏操作,当我们⽤JavaScript时要进⾏转换,较为繁琐;IndexedDB
是被正式纳⼊HTML5标准的数据库储存⽅案,它是NoSQL数据库,⽤键值对进⾏储存,可以进⾏快速读取操作,⾮常适合web场景,同时⽤JavaScript进⾏操作会⾮常便 6. 浏览器事件机制 6.1. 事件 + 事件模型
事件是用户操作网页时发生的交互动作(比如 click/move) / 网页本身的一些操作(文档加载,窗口滚动和大小调整)
事件被封装成一个 event 对象,包含了该事件发生时的所有相关信息( event 的属性)以及可以对事件进行的操作( event 的方法)。
事件是用户操作网页时发生的交互动作或者网页本身的一些操作,现代浏览器一共有三种事件模型:
DOM0 级事件模型IE 事件模型:事件处理阶段 + 事件冒泡阶段DOM2 级事件模型:事件捕获阶段 + 事件处理阶段 + 事件冒泡阶段如何阻止事件冒泡:event.stopPropagation()
事件委托的核心原理:给父节点添加侦听器,利用事件冒泡影响每一个子节点。
事件委托的概念
本质上是利用了浏览器事件冒泡
的机制。因为事件在冒泡过程中会上传到父节点。
父节点可以通过事件对象获取到目标节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件,这种方式称为事件委托(事件代理)
事件委托的特点
不必为每一个子元素都绑定一个监听事件,绑定到他的父层,这样减少内存消耗;
动态新增的元素无需重新绑定事件;
事件委托的局限性
比如 focus、blur 之类的事件没有事件冒泡机制,所以无法实现事件委托;
mousemove、mouseout 这样的事件,虽然有事件冒泡,但是只能不断通过位置去计算定位,对性能消耗高,也不适合事件委托的;
事件委托的使用场景
场景:给页面的所有的a标签添加click事件
document.addEventListener("click", function(e) {
var node = e.target;
while (node.parentNode.nodeName != "BODY") {
if (node.nodeName == "A") {
console.log("a");
break;
}
node = node.parentNode;
}
}, false);
6.3 同步和异步
同步指的前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的;
异步指的是当一个进程在执行某个请求时,如果这个请求需要等待一段时间才能返回,这个时候进程会继续往下执行,不会阻塞等待消息的返回,当消息返回时系统再通知进程进行处理。
同步任务: 都在主线程上执行,形成一个执行栈
(先进先出)
异步任务: JS 的异步是通过回调函数实现的,相关回调函数添加到任务队列
中(任务队列也称为消息队列)
为什么会有事件循环
js 是单线程运行的,也就是说,同一个时间只能做一件事。 单线程会导致有很多任务需要排队一个个执行,如果某个任务执行时间太长,就会出现阻塞,为了解决这个问题,JS引入事件循环机制
什么是事件循环
主线程不断从任务队列中读取事件,这个过程是循环不断的,这种运行机制就叫事件循环(Event Loop)。任务队列可以分为宏任务队列和微任务队列
Event Loop 执行顺序
首先执行同步代码
(属于宏任务)
当执行完所有同步代码后,执行栈为空,查询是否有异步代码需要执行
执行所有微任务
当执行完所有微任务后,如有必要会渲染页面
然后开始下一轮 Event Loop,执行宏任务中的异步代码
6.4 宏任务和微任务 宏任务: script 脚本的执行、setTimeout ,setInterval ,setImmediate 一类的定时事件,还有如 I/O 操作、UI 渲染等微任务: promise 的回调、await/async、node 中的 process.nextTick 、对 Dom 变化监听的MutationObserverconsole.log(1) //同步任务
setTimeout(()=>{ //异步任务宏任务
console.log(2)
}, 0)
new Promise((resolve, reject)=>{ // new Promise同步任务
console.log('new Promise')
resolve()
}).then(()=>{ // //.then 异步任务微任务
console.log('then')
})
console.log(3) //同步任务
// 同步任务 --> 异步任务(微任务 --> 渲染 --> 宏任务)
// 1=>new Promise=> 3 => then => 2
7. 浏览器垃圾回收机制
7.1 哪些操作会造成内存泄漏
使用未声明的变量设置了 setInterval 定时器,而忘记取消它获取一个 DOM 元素的引用,而后面这个元素被删除不合理的使用闭包,导致某些变量一直被留在内存当中
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)