目录
[2.常见 HTTP 状态码](#2.常见 HTTP 状态码)
前言
网络通信篇
1.GET和POST的区别
GET 是获取资源,POST是提交资源(改/写),具体的区别如下表所示:
| 维度 | GET | POST |
|---|---|---|
| 定义 | 获取资源(读),它是幂等的,执行1次和100次对服务器资源不会修改 | 提交资源(写/改),它是幂等的,执行多次会导致资源的创建或修改 |
| 数据位置 | 参数拼接在URL后,参数数量有限 | 参数放在请求体中 |
| 数据大小 | 受限于浏览器/服务器对URL长度的限制 | 理论上无限制(受制于服务器配置) |
| 缓存性 | 能被浏览器主动缓存,会被保存在历史记录中 | 默认不缓存,也不会保留在浏览器历史记录里 |
| 安全性 | 参数直接暴露在地址栏 | 数据在请求体中,但如果不是HTTPS协议,依然是明文传输 |
2.常见 HTTP 状态码
状态码死记硬背即可,主要有四组:"200组 "、"300组 "、"400组 "、"500组"
2XX(成功):
- 200 OK:请求成功
- 204: No Content:请求成功,但是响应请求没有请求体(PUT/DELETE)
- 206 Partial Content:客户端发送了"范围请求",服务器成功返回了部分内容
3XX(重定向):
- 301 Moved Permanently:永久重定向
- 302 Found:临时重定向
- 304 Not Modified:未修改(缓存命中),本地缓存的文件是最新的,不需要再从服务器抓取
4XX(客户端错误):
- 400 Bad Request:请求参数有误,服务器看不懂
- 401 Unauthorized:未授权(未登录就尝试访问需要授权的URL)
- 403 Forbidden:禁止访问
- 404 Not Found:资源未找到
5XX(服务器错误):
- 500 Internal Server Error:服务器代码错误
- 502 Bad Gateway:网关错误
- 503 service Unavaliable:服务器不可用
- 504 Gateway Timeout:网关超时
3.浏览器本地存储方案
浏览器本地存储方案共有四种:
- Cookie
- localStorage
- sessionStorage
- IndexedDB
其中indexDB比较特殊,所以需要单独拿出来说,关于Cookie、localStorage、sessionStorage三者的区别如下表所示:
| 特性 | Cookie | localStorage | sessionStorage |
|---|---|---|---|
| 生命周期 | 由Expires或Max-Age决定,过期前一直有效 | 永久有效,除非手动删除 | 仅当前会话有效,关闭标签页就会被自动删除 |
| 存储大小 | 很小,约4KB | 一般,约5MB | 一般,约5MB |
| 与服务器交互 | 每次请求都会自动携带在Header里 | 不参与服务器通信 | 不参与服务器通信 |
| 使用方法 | document.cookie | localStorage.getItem/ localstorage.setItem | sessionStorage.getItem/ sessionStorage.setItem |
| 适用场景 | 存储SessionI、Token、用户登录状态 | 存储用户设置 | 临时数据 |
关于IndexedDB:
- 它的存储量非常大,取决于你浏览器可以存储的空间(硬盘空间)
- 它是非关系型数据库(NoSQL)
关于IndexedDB的介绍,可以参考另一篇博客:
关于"Cookie和localStorage哪个更安全"这个问题,解释如下:
Cookie如果设置了HttpOnly属性,JS脚本就无法读取它,安全性较高
localStorage是纯JS操作的,一旦网站被XSS漏洞攻击,localStorage里的数据会被读走,所以敏感信息(Token)存放在Cookie里比localStorage更安全
代码手写篇
1.手写Promise.all()
javascript
function myPromiseAll(promises) {
return new Promise((resolve, reject) => {
if (!Array.isArray(promises)) {
return reject(new TypeError('参数不是个数组'));
}
const res = [];
let count = 0;
const length = promises.length;
if (length === 0) {
return resolve(res);
}
promises.forEach((promise, index) => {
Promise.resolve(promise).then(value => {
res[index] = value;
count++;
if (count === length) {
resolve(res);
}
}).catch(err => {
reject(err);
})
})
})
}
测试用例:
javascript
console.log("开始测试 myPromiseAll...");
console.time("Case 1 耗时");
myPromiseAll([
sleep(2000, 'P1 (慢 - 2s)'),
'P2 (普通值 - 0s)',
sleep(1000, 'P3 (快 - 1s)')
]).then(res => {
console.log("Case 1 成功:", res);
console.timeEnd("Case 1 耗时");
// 预期输出: ["P1 (慢 - 2s)", "P2 (普通值 - 0s)", "P3 (快 - 1s)"]
}).catch(err => {
console.error("Case 1 失败:", err);
});
console.time("Case 2 耗时");
myPromiseAll([
sleep(3000, 'P1 (我还没跑完呢)'),
sleep(500, 'P2 (我炸了!)', true),
sleep(1000, 'P3 (我也还没跑完)')
]).then(res => {
console.log("Case 2 居然成功了:", res);
}).catch(err => {
console.log("Case 2 捕获失败:", err);
console.timeEnd("Case 2 耗时");
// 预期输出: "P2 (我炸了!)"
});
myPromiseAll([]).then(res => {
console.log("Case 3 空数组测试:", res);
// 预期输出: []
});
结果:

2.手写instanceof
javascript
function myInstanceof(left, right) {
if (left === null || (typeof left !== 'object' && typeof left != 'function')) {
return false;
}
let proto = Object.getPrototypeOf(left);
const prototype = right.prototype;
while (true) {
if (proto === null) return false;
if (proto === prototype) return true;
proto = Object.getPrototypeOf(proto);
}
}