个人总结八股文的背诵方案
URL到显示网页的过程
- 浏览器解析URL,获取协议,主机名,端口号,路径等信息,并通过DNS查询将主机名转换为对应的IP地址
- 浏览器与服务器建立TCP,进行三次握手。
- 浏览器向服务器发送HTTP请求,包含请求方法 ,请求头,请求体等信息
- 服务器接收并处理HTTP请求,根据请求的路径和参数返回相应的HTTP响应,包含状态码,响应头,响应体等信息
- 浏览器接收并解析HTTP响应,根据状态码和响应头判断响应的结果和类型
- 浏览器根据响应体的内容进行渲染和显示。如果响应体是html文档,浏览器会生成DOM树和CSSOM树,然后生成渲染树,进行布局和绘制。如果响应体是js或css文件,则浏览器会执行js代码或应用css样式。如果响应体是图片或其他资源,浏览器会下载并显示。
- 浏览器会根据情况选择关闭或保持TCP连接,进行四次挥手。
DNS查询:本地域名服务器->host文件->根域名服务器->顶级域名服务器查询->权限域名服务器查询。(可以是递归查询,也可以是迭代查询)巧记:本地host根顶级权限
三次握手
- 客户端随机初始化序号seq=x,同时把 SYN 标志位设置为1,表示 SYN 报文。并发送给服务器
- 服务端收到客户端的 SYN 报文后,随机初始化序号seq=y,确认应答号ack=x+1;并将SYN 和 ACK 标志位都设置为1。发给客户端
- 客户端收到服务器的报文后,ack=y+1,seq = x+1。并发给服务器
seq=x,SYN=1;`` seq=y,ack=x+1,SYN=ACK=1; `` ack=y+1,seq = x+1。
为什么不能两次或四次?
- 如果只有两次握手,那么就无法保证双方都能接收数据。例如,如果客户端发送了连接请求后,由于网络延迟或其他原因,没有收到服务器的连接确认,那么客户端就不知道服务器是否同意连接,也不知道服务器的初始序列号。如果此时客户端开始发送数据,可能会导致服务器无法正确处理或丢弃数据。
- 如果有四次或更多次握手,那么就会浪费时间和资源。例如,如果在第二次握手后,服务器再向客户端发送一个额外的确认,那么这个确认就是多余的,因为客户端已经在第三次握手中确认了服务器的初始序列号。多余的握手会增加网络负担和延迟,并占用双方的缓存空间。
四次挥手
- 客户端发送SYN=1给服务器,之后客户端进入 FIN_WAIT_1 状态。
- 服务器发送ACK给客户端,接着服务端进入 CLOSED_WAIT 状态。客户端收到服务端的 ACK 应答报文后,之后进入 FIN_WAIT_2 状态。
- 服务端处理完数据后,向客户端发送 FIN 报文,之后服务端进入 LAST_ACK 状态。
- 客户端收到服务端的 FIN 报文后,回一个 ACK 应答报文,之后进入 TIME_WAIT 状态。
服务器收到了 ACK 应答报文后,就进入了 CLOSED 状态,至此服务端已经完成连接的关闭。
客户端在经过 2MSL 一段时间后,自动进入 CLOSED 状态,至此客户端也完成连接的关闭。
计算机网络分层模型
- 物理层:物理媒介(双绞线、光纤和无线电波)上传输比特流,并定义了物理设备的接口标准、电气特性和编码方式等。IEEE
- 数据链路层:相邻节点之间传输帧,并提供差错控制和流量控制。PPP、SLIP
- 网络层:将数据报从源主机发送到目的主机,并提供路由选择和拥塞控制。IP、ICMP、ARP
- 传输层:传输报文段,进程之间的通信。TCP和UDP
- 会话层:建立会话、session验证,断点传输。SMTP、DNS
- 表示层:数据转换、加密、压缩。TELNET、SNMP
- 应用层:用户界面的交互。FTP,HTTP、NFS、SSL
上述是OSI七层模型,TCP/IP五层模型:应用层,表示层和会话层合并为应用层;TCP/IP四层模型:物理层和数据链路层合并为网络接口层
TCP通信和UDP通信各自的优缺点
- TCP优点:可靠稳定,TCP通过三次握手建立连接,通过确认、重传、窗口、拥塞机制等保证数据无差别、不丢失、不重复、按序到达。
缺点:效率低,占用系统资源高,易被攻击。面向连接只能是点到点通信。 - UDP优点:效率高且安全。面向报文,可以进行一对多和多对多通信。
进程和线程的区别,加一点协程
- 资源:进程是资源分配的基本单位,而线程是操作系统调度和执行的基本单位。进程有自己独立的地址空间和资源,而线程共享所属进程的资源,但有自己的栈和局部变量。
- 开销:进程的创建和销毁都需要向操作系统申请或释放资源,涉及到保存和恢复上下文,开销较大。线程的创建和销毁只需要在用户空间内进行,涉及到部分上下文的切换,开销较小。
- 通信:进程间通信需要借助操作系统提供的 IPC 机制,如管道、信号、消息队列等。而线程间可以直接读写同一进程中的数据,只需要同步控制即可。
- 稳定性:进程之间是相互隔离的,一个进程崩溃不会影响其他进程的运行;线程之间是相互依赖的,一个线程崩溃可能导致整个进程终止。
- 协程是一种用户态的轻量级线程,由程序员控制其创建、调度和销毁,不需要操作系统的支持。协程之间是相互独立的,一个协程崩溃不会影响其他协程的运行。
进程切换的过程
- 保存当前运行进程的上下文,包括程序计数器、栈指针、寄存器、内核数据结构等信息,以便下次恢复执行。
- 根据调度算法选择一个就绪态的进程作为切换的进程。
- 恢复第一步保存的上下文,包括程序计数器、栈指针、寄存器、内核数据结构等信息。
- 转移CPU的控制权给被选中的进程,开始执行。
进程间通信方式,线程多了全局变量
- 管道:半双工通信方式,数据只能在父子进程间单向流动。
- 命名管道:有路径名关联,可以在任意进程间通信。
- 消息队列:存放在内核中的消息链表,支持多个进程间通信
- 信号量:实现进程间的互斥与同步
- 共享内存:多个进程直接访问同一块物理内存空间。
陈述http
- HTTP,全称为 HyperText Transfer Protocol,即为超文本传输协议。是互联网应用最为广泛的一种网络协议
所有的 www 文件都必须遵守这个标准。 - http特性:无连接无状态、构建于 TCP/IP 协议之上、默认端口号80、分为请求和响应两个部分。
- 请求:GET,POST,PUT,DELETE
- 响应:200 OK、301永久重定向、302临时重定向、304未修改、400客户端语法错误、401未授权、403Forbidden 、404 Not Found、500服务器内部错误、503服务器暂时错误
- http缺点:通信使用明文,内容可能被窃听。
通信双方的身份无法得到认证,身份可能遭遇伪装。
无法验证报文的完整性。 - https可以简单的理解为:https = http + 加密 + 认证 + 完整性保护。
- 完整性保护:对数据的散列值(哈希值)进行加密,然后将其附加在传输的数据上。接收方解密之后再验证数据与散列值是否对应。
- 加密:SSL/TLS 使用公钥加密和私钥解密的方式来保护数据的机密性。
过程:S发公钥给C,C用公钥加密一个随机生成的对称密钥,然后发给S,S用原有的私钥来解密这个对称秘钥,之后C和S采用这个对称秘钥来加解密数据。
http有哪些版本?每个版本分别加了哪些新特性?
- HTTP 0.9:是第一个版本的HTTP协议,已过时。组成简单,只有GET请求,且不支持请求头,只支持纯文本。HTTP 0.9具有典型的无状态性,每个事务独立进行处理,事务结束时就释放这个连接。
- HTTP 1.0:
引入了请求方法,GET、HEAD、POST,开始支持客户端通过POST方法向Web服务器提交数据
引入了内容协商,用于让客户端和服务器协商最合适的内容格式,如语言、字符集、编码等。
引入了状态码、头部字段、短连接和缓存机制。 - HTTP 1.1:
引入了请求方法,OPTIONS, PUT, DELETE, TRACE, CONNECT方法
引入了管道机制,允许客户端在收到上一个响应之前就发送下一个请求,进一步减少了网络延迟。
引入了分块传输编码,将内容分成多个块发送,每个块包含自己的大小信息。
完善缓存机制,加入了一些cache的新特性,引入了实体标签,一般被称为e-tags,新增更为强大的Cache-Control头。
引入了持久连接、引入虚拟主机:在同一个IP地址和端口上提供多个不同域名的服务 - HTTP2.0
引入了二进制分帧,信息分割为更小的帧,并采用二进制编码,从而降低了报文解析的复杂度和开销。
引入了多路复用,在同一个TCP连接上同时发送和接收多个请求和响应
引入了首部压缩,通过HPACK算法对请求和响应的头部字段进行压缩。
引入了服务器推送,服务器可以在客户端请求之前主动发送数据,预加载一些客户端可能需要的资源。
引入了优先级和流量控制,即客户端和服务器可以为不同的请求设置优先级,让重要的请求优先处理,同时可以控制数据流的速度,避免拥塞和浪费。 - HTTP 3.0
使用QPACK算法对HTTP头部进行压缩,提高了编码效率和压缩率。
使用QUIC协议代替TCP协议,实现了无序、并发的字节流传输,解决了队头阻塞问题。
0-RTT握手:允许客户端在第一次请求时就发送数据。
WebSocket
- 实时性:WebSocket允许服务器主动向客户端推送数据,实现实时通信,无需客户端发起请求。
- 全双工通信:WebSocket允许客户端和服务器同时发送和接收数据,实现真正的双向通信。
- 较低的延迟:由于WebSocket在建立连接后保持长连接,减少了连接和关闭的开销,因此具有较低的延迟。
- 较低的延迟:由于WebSocket在建立连接后保持长连接,减少了连接和关闭的开销,因此具有较低的延迟。
- 跨域支持:WebSocket支持跨域通信,不受同源策略限制。
强缓存和协商缓存
- 强缓存:当缓存未过期时,直接从本地缓存中加载资源。字段包括 Expires(HTTP/1.0)和 Cache-Control(HTTP/1.1)
- 协商缓存:本地缓存已过期,则发请求询问服务器资源是否有更新;服务器根据 Last-Modified 或 ETag 来判断,若未更新则返回304 Not Modified 状态码继续使用本地资源,否则返回200状态码和新的资源。
ARQ协议
- 自动重传请求协议,是一种用于实现可靠数据传输的协议。它通过使用确认和超时这两个机制,在不可靠服务的基础上实现可靠的信息传输。如果发送方在发送后一段时间之内没有收到确认帧,它通常会重新发送。
- 停止等待ARQ协议:是指发送方每发送一个分组就停止发送,等待接收方的确认。如果发送方在超时时间内没有收到确认,就重发该分组。这种协议简单易实现,但信道利用率较低。
- 连续ARQ协议:是指发送方可以连续发送多个分组,不必每发完一个分组就停顿下来等待对方的确认。这样可以提高信道利用率,但也增加了复杂性和开销。连续ARQ协议又分为回退N帧ARQ协议和选择重传ARQ协议。
- 回退N帧ARQ协议:某个分组出错或丢失,就丢弃该分组及其后续的分组。选择重传ARQ协议:某个分组出错或丢失,就缓存该分组之后正确接收的分组,并对每个正确接收的分组单独发送选择性确认。
常见的攻击类型CSRF,XSS,DDoS,点击劫持,中间人攻击,DNS 劫持
- CSRF:用户未退出网站A,同一个浏览器中访问网站B,网站B携带cookie向网站A发送请求获取用户信息,网站A根据cookie会响应该请求。解决方法:服务器进行同源检测、设置http-only:true,验证Token。
- XSS:存储型、反射型、DOM。存储型:将恶意代码提交到服务器;反射型:恶意代码放在URL;DOM:通过恶意脚本修改页面的 DOM 结构。解决方法:对用户输入进行编码、校验过滤特殊字段、保护cookie
- ddos:多个设备向目标服务器发送大量请求,导致目标服务器无法正常提供服务或者奔溃。解决方法:限制ip访问频率、使用负载均衡和缓存、使用CDN、云防火墙等第三方防御服务。
- 点击劫持:通过透明的iframe或其他可点击元素覆盖在目标网站上,欺骗用户点击来窃取用户信息。解决方法:设置 X-Frame-Options 响应头(DENY、SAMEORIGIN、SAMEORIGIN)是否允许其他网页的iframe显示、js检测是否嵌套其他网页,选择跳出或提示用户。
- 中间人攻击:在用户和目标网站之间截取通信信息,获取用户敏感信息或篡改数据。解决方法:HTTPS协议、避免使用公共wifi。
- DNS劫持:篡改DNS服务器或本地hosts文件,使得用户访问的域名解析到别的ip地址,从而访问到假冒的网站。解决方法:时刻手动维护本地hosts文件,使用可靠的 DNS 服务器。
JavaScript 的事件循环机制
- js是单线程的,如果遇到异步任务,如 setTimeout、Promise、Ajax 等,就会将它们放入一个任务队列中,等待当前的同步任务执行完毕后,再按照一定的规则从任务队列中取出异步任务执行。这个过程就是事件循环。
- 同步代码执行完毕时,事件循环会检查微任务队列并依次执行完,然后会检查宏任务队列并依次执行完。
- 宏任务包括 setTimeout、setInterval、Dom事件、setImmediate、requestAnimationFrame、I/O、UI rendering 等,微任务包括 Promise、async/await、MutationObserver、process.nextTick 等。
JavaScript new的过程
- 创建一个空的简单 JavaScript 对象(即 {} );
- 将这个空对象的原型指向构造函数的原型,即设置 proto 属性;
- 将这个空对象作为 this 的上下文传递给构造函数,并执行构造函数中的代码;
- 如果构造函数没有显式返回一个对象(返回的是基本类型也不行),则返回这个空对象,否则返回构造函数返回的对象。
说一下Chrome的进程架构
- 浏览器进程:负责界面显示、用户交互、子进程管理,同时提供存储等功能。
性能优化
- 访问网站前:
(1) 推送资源:预先将页面资源如JS,图片,多媒体文件推送到客户端/浏览器
(2) 预加载: prefetch(可能使用的资源)、preload(必要资源)、prerender
(3) 预先请求AJAX:提前获取下个跳转页面需要的ajax数据,缓存到localstorage - 加载过程中:
(1) 查询强缓存:service worker、强缓存
(2) 解析dns:
(3) 建立tcp链接:http1.1持久链接、http2多路复用
(4) 发送请求: 精灵图、disk cache协商缓存、小图片base64免去请求
(5) 解析html:css在上,js在下避免阻塞
(6) 构建渲染树:减少DOM的数量和嵌套层级、减少重绘重排、懒加载
(7) 运行JS:精简代码、代码分割、tree shaking - 页面运行时:
(1) 虚拟滚动条应对无限加载
(2) 节流防抖
(3) 内存:避免全局变量、避免使用闭包、手动回收(obj=null)
同源策略与跨域 https://www.nowcoder.com/discuss/514959073205370880
- 域名、协议、端口号任意一个不同则为跨域。
- 解决跨域:JSONP(script标签可以跨域加载资源)、CORS(Cross-Origin Resource Sharing、服务端响应头"Access-Control-Allow-Origin")、代理服务器、WebSocket协议不受同源策略限制、postMessage
XMLHttpRequest 和 fetch 区别 https://blog.csdn.net/weixin_43073401/article/details/132001688
- 用法:xhr用法比较复杂,依次创建对象、设置请求属性、监听状态变化、发送请求;fetch 比较简单,只需要调用fetch函数并传入参数即可
- 返回值:xhr返回的是xhr对象,通过responseText 或 responseXML获取数据;fetch返回一个Promise 对象,通过response.json() 或 response.text()获取数据
- 跨域请求:xhr跨域时需要设置withCredentials为 true,同时服务器端需要设置允许跨域请求的头信息。fetch默认不会发送cookie,可设置 credentials: ‘include’ 来携带Cookie。'omit’不会携带cookie,'same-origin’同源时携带cookie
- 错误处理:xhr可以通过onerror 和 onreadystatechange 等事件来处理错误;fetch需要手动检查响应的 ok 属性来处理错误
- 兼容性:xhr支持广泛,包括老旧浏览器;fetch 是ES6的新特性,不支持IE浏览器(除了Edge)和一些旧版本浏览器,但可以通过polyfill来实现兼容。
异步加载js https://www.jb51.net/article/107680.htm
- 给 script 标签添加 async 属性:异步加载脚本,加载完成后立即执行,加载顺序并不是固定的。
- 给 script 标签添加 defer 属性:异步加载脚本,文档解析完成后执行,按照在页面中出现的顺序执行。
- JavaScript动态创建
Session、Cookie和Token https://www.nowcoder.com/discuss/515115466998734848
- Session是服务器端的会话状态管理机制,首次访问服务器时会创建一个唯一的session id通过Set-Cookie返回给客户端,存储在服务器内存或数据库占用服务器资源。
- Token是身份验证和授权的令牌,由服务器生成发给客户端,不依赖于服务器的会话存储。
- Cookie是存储在浏览器中的文本文件,后续的请求会携带相应的cookie信息,由于存在客户端,所以存在被篡改和劫持的风险。
- cookie属性:name、value、domain、path、expires或max-age、secure(HTTPS)、HttpOnly、SameSite:(“Strict”、“Lax"或"None”)。
ES6及以上新特性
- ES6:let,const、箭头函数、模板字符串、解构赋值、扩展运算符、默认参数值、类和继承、Promise、Set 和 Map 、Symbol
- ES7:数组includes、指数操作符(**)
- ES8:async/await、values/entries、padStart/padEnd、函数参数列表结尾允许逗号、Object.getOwnPropertyDescriptors()
- ES9:异步迭代器、Promise.finally()、Rest/Spread 属性、正则表达式命名捕获组/反向断言/dotAll模式
- ES10:flat扁平化、flatMap映射数组、trimStart/trimEnd、String.prototype.matchAll、Symbol.prototype.description、Object.fromEntries()、JSON Superset 超集、JSON.stringify() 加强格式转化、Array.prototype.sort() 更加稳定、Function.prototype.toString() 重新修订
- ES11:可选链操作符(?.)、空位合并操作符(??)、动态 import ()、BigInt、globalThis、Promise.allSettled、for in 结构
- ES12:replaceAll、Promise.any、逻辑赋值操作符 ??=、&&=、 ||=、WeakRef(ref.deref())、数字下划线分隔符、Intl.ListFormat、Intl.DateTimeFormat
- ES13:类私有方法和字段(#前缀)、可索引数据上新增.at()方法、Object.hasOwn(object, property)
require和import区别:
- import是ES6语法,require是commonJS语法。
- 导入文件类型:import只能导入ES6模块或者使用Babel等工具转化为ES6模块的代码,而require可以导入CommonJS模块、AMD模块、UMD模块以及Node.js内置模块等多种类型的模块。
- 变量提升:import语句是静态执行的(import()是运行时执行,动态导入),并在模块内部创建一个局部作用域,不会变量提升,因此需要将语句放在文件顶部;require函数是动态执行的,这意味着它在运行时执行,可以变量提升。
- 导出方式:import对应的导出为export xxx 或export default {};而require对应的导出为module.exports = {};
- 导入内容:require 请求整个包对象,import 只请求模块中需要的部分;
浏览器的前端存储方案
- cookies:Cookies 可以用于存储少量数据,并且有一定的过期时间,但由于每次请求都会携带 Cookies,所以不适合存储大量数据。
- Web Storage(localStorage 和 sessionStorage)
- IndexedDB:是一种客户端数据库,可以在浏览器中存储大量结构化数据。它提供了类似于 SQL 的查询功能,并且数据可以持久化保存在客户端。
- Cache Storage:是 Service Worker 的一部分,用于缓存网络请求的数据,可以实现离线访问和提高应用性能
- WebSQL(已废弃):是一种在客户端使用 SQL 数据库的方案,但已被废弃,不推荐使用。
js设计模式
- 单例模式:确保一个类只有一个实例,并提供一个全局访问点。用来管理全局状态、配置等。
- 观察者模式:定义了一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会收到通知并自动更新。
- 发布订阅模式:在观察者模式基础上解耦了发布者(Publisher)和订阅者(Subscriber),通过一个消息中心作为媒介。
- 策略模式:一个功能有多种方案可以选择,封装各个方案,并且使他们能互相替换。(抽取公共逻辑)
- 代理模式:为其他对象提供一种代理以控制对这个对象的访问。保护代理、虚拟代理、缓存代理
- 迭代器模式:提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。如js的forEach、map、some等(Iterator和 Generator)
- 适配器模式:解决两个接口/方法间的接口不兼容的问题。
- 享元模式:大量相似对象,抽出共同部分属性作为内部状态,其他属性作为外部状态。(抽取公共属性)
- 装饰器模式:在不改变原有对象结构的基础上,动态地给对象增加新的功能或者增强原有功能。(高阶组件)