网络相关
TCP 和 UDP 的区别
| - | TCP | UDP |
|---|---|---|
| 是否连接 | 面向连接 | 无连接 |
| 是否可靠 | 可靠,使用流量控制和拥塞控制 | 不可靠,不使用流量控制和拥塞控制 |
| 连接对象个数 | 只能是一对一 | 可以一对一,一对多,多对多交互通信 |
| 传输报文 | 面对字节流 | 面向报文 |
| 首部开销 | 最小20字节,最大60字节 | 仅8字节 |
| 适用场景 | 适用于要求可靠传输的场景 | 实时应用(直播,IP电话,视频会议等) |
TCP 连接的三次握手和断开连接的四次挥手
三次握手的动态过程
- 客户端首先向服务器端发送一段
TCP报文,表示发起连接请求
- 标记位为
SYN,表示“请求建立新连接”; - 序号为
Seq=X(X一般为1); - 随后客户端进入
SYN-SENT阶段。
- 服务器端接收到
TCP报文之后,结束LISTEN阶段,并返回一段TCP报文
- 标志位为
SYN和ACK,表示“确认客户端的报文Seq序号有效,服务器能正常接收客户端发送的数据,并同意创建新连接”(即告诉客户端,服务器收到了你的数据); - 序号为
Seq=y; - 确认号为
Ack=x+1,表示收到客户端的序号Seq并将其值加1作为自己确认号Ack的值;随后服务器端进入SYN-RCVD阶段。
- 客户端收到服务器端确认收到数据的
TCP报文之后,结束SYN-SENT阶段。并返回最后一段TCP报文
- 标志位为
ACK,表示“确认收到服务器端同意连接的信号”(即告诉服务器,我知道你收到我发的数据了); - 序号为
Seq=x+1,表示收到服务器端的确认号Ack,并将其值作为自己的序号值; - 确认号为
Ack=y+1,表示收到服务器端序号Seq,并将其值加1作为自己的确认号Ack的值; - 随后客户端进入
ESTABLISHED阶段。
服务器收到来自客户端的“确认收到服务器数据”的 TCP 报文之后,明确了从服务器到客户端的数据传输是正常的。结束 SYN-SENT 阶段,进入 ESTABLISHED 阶段。
断开连接的四次挥手
- 首先客户端想要释放连接,向服务器端发送一段
TCP报文,表示请求释放连接 - 服务器端接收到客户端的
TCP报文之后,确认了客户端想要释放连接,随后服务器端结束ESTABLISHED阶段,进入CLOSE-WAIT阶段(半关闭状态)并返回一段TCP报文,表示接收到客户端释放连接的请求,并准备开始释放连接 - 当服务器做好了释放连接的准备之后,再向客户端发送一段
TCP报文,此时结束CLOSE-WAIT阶段,进入LAST-ACK阶段,并且停止服务器端->客户端发送数据,但仍能够接收到客户端传输过来的数据 - 客户端收到服务器端发出的
TCP报文之后,确认了服务器端已经做好释放连接的准备,结束FIN-WAIT-2阶段,进入TIME-WAIT阶段,并向服务器端发送一段报文,随后客户端在TIME-WAIT阶段等待 2MSL
服务端接收到从客户端发出的 TCP 报文之后,结束 LAST-ACK 阶段,进入 CLOSED 阶段,此时正式关闭服务器到客户端方向的连接;客户端等待完 2MSL 之后,结束 TIME-WAIT 阶段,进入 CLOSED 阶段,完成四次挥手。
HTTP 和 HTTPS 的区别
HTTP
- 无状态:协议对客户端没有状态存储,例如访问一个网站需要反复进行操作
- 无连接:每次请求都需要通过
TCP的三次握手和四次挥手,耗费不必要的时间和流量 - 基于请求和响应:基本的特性,有客户端发起请求,服务端响应
- 简单快速,灵活
- 使用明文通信,无法确保数据的完整性
HTTPS(基于HTTP协议,通过SSL或TLS提供加密处理数据、验证对方身份以及数据完整性保护)
- 内容加密:采用混合加密技术(非对称加密和对称加密),中间者无法直接查看明文内容
- 验证身份:通过证书认证客户端访问的是自己的服务器
- 保护数据完整性:防止传输的内容被中间人冒充或者篡改
GET 和 POST 的区别
表面区别
-
GET在浏览器回退时是无害的,而POST会再次提交请求。 -
GET产生的URL地址可以被Bookmark,而POST不可以。 -
GET请求会被浏览器主动cache,而POST不会,除非手动设置。 -
GET请求只能进行url编码,而POST支持多种编码方式。 -
GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。 -
GET方式提交数据的大小(一般来说1024字节),http 协议并没有硬性限制,而是与浏览器、服务器、操作系统有关,而POST理论上来说没有大小限制,http 协议规范也没有进行大小限制,但实际上POST所能传递的数据量根据取决于服务器的设置和内存大小。 -
对参数的数据类型,
GET只接受 ASCII 字符,而POST没有限制。 -
GET比POST更不安全,因为参数直接暴露在 URL 上,所以不能用来传递敏感信息。 -
GET参数通过 URL 传递,POST放在 Request body 中。
重大区别
GET产生一个TCP包,POST产生两个
GET:浏览器会把 http header 和 data 一并发送出去,服务器响应200(返回数据)
POST:浏览器先发送 header,服务器响应100 continue,浏览器再发送 data,服务器响应200 ok(返回数据)
XSS vs CORS
| - | XSS | CORS |
|---|---|---|
| 含义 | 跨站脚本攻击 | 跨站脚本伪造 |
| 防范 | token 存在 cookie 中,设置 httpOnly | 在请求头中携带 cookie |
js 相关
闭包
- 含义:函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起构成闭包(closure)。也就是说,闭包可以让你从内部函数访问外部函数作用域。在 JavaScript 中,每当函数被创建,就会在函数生成时生成闭包。
- 用处:闭包很有用,因为它允许将函数与其所操作的某些数据(环境)关联起来。这显然类似于面向对象编程。在面向对象编程中,对象允许我们将某些数据(对象的属性)与一个或者多个方法相关联。
因此,通常你使用只有一个方法的对象的地方,都可以使用闭包。
例如修改 fontSize 这个方法:
function makeSizer(size) {
return function() {
document.body.style.fontSize = size + 'px'
}
}
const size12 = makeSizer(12)
const size16 = makeSizer(16)
原型链
prototype
在 JavaScript 中,每个函数都有一个 prototype 属性,该属性指向函数的原型对象。
function Person(name) {
this.name = name
}
Person.prototype.age = 23
const person1 = new Person()
const person2 = new Person()
console.log(person1.age) // 23
console.log(person2.age) // 23
上述例子中,构造函数的 prototype 指向了一个对象,而这个对象正是调用构造函数创建实例的原型,即 person1 和 person2 的原型。
原型:每一个 javaScript 对象(除 null 外)被创建的时候,就会与之关联另一个对象,这个对象就是“原型”,每一个对象都会从原型中“继承”属性。
__proto__
这是每个对象(除 null 外)都会有的属性,该属性指向对象的原型。
function Person() {
}
const person = new Person();
console.log(person.__proto__ === Person.prototype); // true
constructor
每个原型都有一个 constructor 属性,该属性指向该原型关联的构造函数。
- 实例与原型
当读取实例的属性找不到时,就会去查找该实例的原型,如果还没有,就继续沿着 __proto__ 向上查找,一直找到最顶层为止。
- 总结:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。那么假如我们让原型对象等于另一个类型的实例,结果会怎样?显然,此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立。如此层层递进,就构成了实例与原型的链条。这就是所谓的原型链的基本概念。——摘自《javascript高级程序设计》
Eventloop
EventLoop是一个程序结构,用于等待和发送消息和事件。 程序中设置两个线程,一个负责程序本身的运行,叫做主线程;另一个负责主线程与其他线程(主要是 IO 操作)的通信,称为EventLoop线程(消息线程)。 主线程开始运行,每当遇到 IO 操作,主线程就让EventLoop线程通知相应的 IO 程序,主线程接着往后运行,当 IO 完成之后,EventLoop线程再把结果返回主线程。主线程调用事先设定的回调函数,完成任务。MacroTask(宏任务)
script 全部代码、setTimeout、setInterval、setImmediate(浏览器暂时不支持,只有IE10支持,具体可见MDN)、I/O、UI Rendering。
MicroTask(微任务)
Process.nextTick(Node 独有)、Promise、MutationObserver
- 每次单个宏任务执行完毕后,检查微任务(
microTask)队列是否为空,如果不为空的话,会按照先入先出的规则全部执行完微任务(microTask)后,设置微任务(microTask)队列为 null,然后再执行宏任务,如此循环。
数组去重
排序算法
-
冒泡排序
-
快速排序
-
选择排序
-
插入排序
深拷贝浅拷贝
vue
vue 的生命周期
-
官网图解
vue 的路由模式
-
hash
hash 虽然出现 URL 中,但不会被包含在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。
-
history
利用了HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法。支持传入 data,title,url
注意:前端的url必须和实际向后端发起请求的url 一致,如 www.abc.com/book/id 。如果后端缺少对 /book/id 的路由处理,将返回 404 错误。