diff --git "a/docs/\351\235\242\350\257\225\345\244\215\347\233\230/2024\345\271\2644\346\234\2101\345\217\267.md" "b/docs/\351\235\242\350\257\225\345\244\215\347\233\230/2024\345\271\2644\346\234\2101\345\217\267.md"
index 067d2170..7ed76cb8 100644
--- "a/docs/\351\235\242\350\257\225\345\244\215\347\233\230/2024\345\271\2644\346\234\2101\345\217\267.md"
+++ "b/docs/\351\235\242\350\257\225\345\244\215\347\233\230/2024\345\271\2644\346\234\2101\345\217\267.md"
@@ -44,6 +44,19 @@
## 5. get 和 post 的区别
+### 协议层面
+
+语义上的区别
+
+get 从服务器上获取数据
+post 向服务器传递数据
+
+### 应用层面
+
+GET 的请求体为空,即请求体是空字符串(没有请求体是违反 http 协议的,所以 get 的请求体是空字符串,而不是没有)
+
+### 浏览器层面
+
- get 在浏览器回退时是无害的,而 post 会再次发送请求,get 请求可以直接在浏览器中访问,支持刷新和后退,而 post 不能直接在浏览器访问,刷新后数据要重新发送。
- get 产生的 url 地址可以被标记(Bookmark),而 post 不可以
@@ -376,5 +389,5 @@ const onChange = (e) => {
setValue(e.target.value);
};
-
+;
```
\ No newline at end of file
diff --git "a/docs/\351\235\242\350\257\225\345\244\215\347\233\230/\347\254\254\344\270\200\347\211\210\351\235\242\350\257\225\351\242\230.md" "b/docs/\351\235\242\350\257\225\345\244\215\347\233\230/\347\254\254\344\270\200\347\211\210\351\235\242\350\257\225\351\242\230.md"
index 1b0b5673..d872d7ca 100644
--- "a/docs/\351\235\242\350\257\225\345\244\215\347\233\230/\347\254\254\344\270\200\347\211\210\351\235\242\350\257\225\351\242\230.md"
+++ "b/docs/\351\235\242\350\257\225\345\244\215\347\233\230/\347\254\254\344\270\200\347\211\210\351\235\242\350\257\225\351\242\230.md"
@@ -2,21 +2,21 @@
1. typeof
- 对象({})、数组([])、null 的结果都是 object
+ 对象({})、数组([])、null 的结果都是 object
- 新数据类型如Symbol、BigInt,无法识别
+ 新数据类型如 Symbol、BigInt,无法识别
2. instanceof
- 无法判断基本数据类型和null
+ 无法判断基本数据类型和 null
3. Object.prototype.toString.call()
- 语法相对复杂,但是可以区分数组、函数等引用数据类型
+ 语法相对复杂,但是可以区分数组、函数等引用数据类型
4. Array.isArray()
- 只能判断数组类型,精准判断数组
+ 只能判断数组类型,精准判断数组
typeof 和 instanceof 的区别:
@@ -26,8 +26,6 @@ typeof 和 instanceof 的区别:
精确性:typeof 对基本数据类型判断比较精确,对于引用类型则无法进一步区分。instanceof 可以准确的判断引用类型。
-
-
# 防抖和节流
## 防抖
@@ -38,14 +36,14 @@ typeof 和 instanceof 的区别:
```js
const debounce = (fn, delay) => {
- let timer = null;
- return (...args) => {
- clearTimeout(timer);
- timer = setTimeout(()=>{
- fn(args);
- }, delay)
- }
-}
+ let timer = null;
+ return (...args) => {
+ clearTimeout(timer);
+ timer = setTimeout(() => {
+ fn(args);
+ }, delay);
+ };
+};
```
## 节流
@@ -56,16 +54,16 @@ const debounce = (fn, delay) => {
```js
const trottle = (fn, delay) => {
- let timer = null;
- return function (...args) {
- if(timer) return;
- timer = setTimeout(() => {
- fn(args);
- clearTimeout(timer);
- timer = null;
- }, delay)
- }
-}
+ let timer = null;
+ return function (...args) {
+ if (timer) return;
+ timer = setTimeout(() => {
+ fn(args);
+ clearTimeout(timer);
+ timer = null;
+ }, delay);
+ };
+};
```
![image-20240312192537719](/Users/fiat_lux/Library/Application Support/typora-user-images/image-20240312192537719.png)
@@ -84,17 +82,19 @@ const trottle = (fn, delay) => {
如果对象中包含循环引用,会抛出错误;
-对于包含Symbol、RegExp等特殊类型的对象,可能无法正确工作
+对于包含 Symbol、RegExp 等特殊类型的对象,可能无法正确工作
```js
const obj = {
- [Symbol.for('key1')]: 'a',
- b: undefined,
- c: NaN,
- d: () => { return null },
- e: Infinity,
- f: null
-}
+ [Symbol.for('key1')]: 'a',
+ b: undefined,
+ c: NaN,
+ d: () => {
+ return null;
+ },
+ e: Infinity,
+ f: null,
+};
console.log(JSON.parse(JSON.stringify(obj))); // {c: null, e: null, f: null}
```
@@ -103,7 +103,7 @@ console.log(JSON.parse(JSON.stringify(obj))); // {c: null, e: null, f: null}
## 使用 js 工具库 lodash
```js
-const obj = {a: 1, b: 2, c: 3};
+const obj = { a: 1, b: 2, c: 3 };
const newObj = _.cloneDeep(obj);
```
@@ -111,29 +111,27 @@ const newObj = _.cloneDeep(obj);
```js
function deepClone(obj) {
- // 先判断 obj 的数据类型
- if(obj === null) return obj; // obj 为 null
- if(obj instanceof Date) return new Date(obj); // obj 为 Date
- if(obj instanceof RegExp) return new RegExp(obj); // obj 为 RegExp
- if(typeof obj !== 'object') return obj;
- let cloneObj = new obj.constructor();
- for(let key in obj) {
- if(obj.hasOwnProperty(key)) {
- // 实现一个递归拷贝
- cloneObj[key] = deepClone(obj[key]);
+ // 先判断 obj 的数据类型
+ if (obj === null) return obj; // obj 为 null
+ if (obj instanceof Date) return new Date(obj); // obj 为 Date
+ if (obj instanceof RegExp) return new RegExp(obj); // obj 为 RegExp
+ if (typeof obj !== 'object') return obj;
+ let cloneObj = new obj.constructor();
+ for (let key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ // 实现一个递归拷贝
+ cloneObj[key] = deepClone(obj[key]);
+ }
}
- }
- return cloneObj;
+ return cloneObj;
}
```
-
-
扩展:
JSON.stringify(value, replacer, space)
-参数一:value 表示要被序列化的对象,接受对象或数组类型
+参数一:value 表示要被序列化的对象,接受对象或数组类型
参数二:replacer 用于标记需要序列化的属性,接受数组和函数类型
@@ -143,10 +141,10 @@ JSON.stringify(value, replacer, space)
1. localStorage 的存储
- localStorage 只能存储字符串类型,kv(key,value) 结构
+ localStorage 只能存储字符串类型,kv(key,value) 结构
```js
-const obj = {a: 1, b: 2, c: 3};
+const obj = { a: 1, b: 2, c: 3 };
// 序列化要存储的数据: JSON.stringify(obj)
// 存储
localStorage.setItem('obj', JSON.stringify(obj));
@@ -158,77 +156,59 @@ localStorage.removeItem('obj');
2. 对象的深拷贝
- ```js
- const obj = {a: 1, b: 2, c: 3};
- const objA = obj;
- const objB = JSON.parse(JSON.stringify(obj));
- // 修改
- objA.a = 11;
- console.log(obj); // {a: 11, b: 2, c: 3}
- console.log(objA); // {a: 11, b: 2, c: 3}
-
- objB.a = 123;
- console.log(obj); // {a: 11, b: 2, c: 3}
- console.log(objB); // {a: 123, b: 2, c: 3}
- ```
-
-3. 删除对象属性
-
- ```js
- const obj = {a: 1, b: 2, c: 3};
- const str = JSON.stringify(obj, (key, value) =>{
- if(key === 'b') {
- return undefined;
- }
- return value;
- });
- console.log(str); // '{"a":1,"c":3}'
- const objA = JSON.parse(str);
- console.log(objA); // {a: 1, c: 3}
- ```
-
-
-
+ ```js
+ const obj = { a: 1, b: 2, c: 3 };
+ const objA = obj;
+ const objB = JSON.parse(JSON.stringify(obj));
+ // 修改
+ objA.a = 11;
+ console.log(obj); // {a: 11, b: 2, c: 3}
+ console.log(objA); // {a: 11, b: 2, c: 3}
+ objB.a = 123;
+ console.log(obj); // {a: 11, b: 2, c: 3}
+ console.log(objB); // {a: 123, b: 2, c: 3}
+ ```
+3. 删除对象属性
+ ```js
+ const obj = { a: 1, b: 2, c: 3 };
+ const str = JSON.stringify(obj, (key, value) => {
+ if (key === 'b') {
+ return undefined;
+ }
+ return value;
+ });
+ console.log(str); // '{"a":1,"c":3}'
+ const objA = JSON.parse(str);
+ console.log(objA); // {a: 1, c: 3}
+ ```
# 前端跨域
跨域是前端解决的范畴
-
-
什么时候会发生跨域
跨域是由于浏览器的同源策略(协议、域名、)所导致的,是发生在 页面 到 服务端 请求的过程中
-
-
项目中怎么解决这个跨域问题的
1. Nginx 反向代理
2. 搭建 BFF 层
-
-
-
-
了解后端处理跨域的原理吗
-可以使用nginx,但是我们项目后端是在微服务中处理跨域
-
-
+可以使用 nginx,但是我们项目后端是在微服务中处理跨域
cookie 和 localStorage 的区别
-
-
-项目中的登录是用的cookie还是localStorage来保存token的?
+项目中的登录是用的 cookie 还是 localStorage 来保存 token 的?
cookie
-用户在浏览器这边进行登录接口请求,服务端收到这个请求之后,在用户名和密码都正确的情况下,服务器在向浏览器返回登录结果的时候,会生成一个cookie,并且在 Http Response Header 中 Set-Cookie。这样,当浏览器再次请求服务端时,都会同步的带上 cookie,cookie 会附带在每个 Http 请求上。
+用户在浏览器这边进行登录接口请求,服务端收到这个请求之后,在用户名和密码都正确的情况下,服务器在向浏览器返回登录结果的时候,会生成一个 cookie,并且在 Http Response Header 中 Set-Cookie。这样,当浏览器再次请求服务端时,都会同步的带上 cookie,cookie 会附带在每个 Http 请求上。
生成机制
@@ -236,34 +216,41 @@ cookie
2. 客户端生成,通过 document.cookie 设置
-
-
Cookie 设置初衷是用于**维持 HTTP 状态**,不用于**存储数据**。因此 cookie 有以下缺点:
1. 大小限制:每个 cookie 项只能存储 **4K** 数据
2. 性能浪费: cookie 附带在 http 请求上,数据量过大,会导致每个 http 请求就非常庞大,会很消耗流量和带宽。
-
-
前端和后端是同一个域名吗?
那肯定不是同一个
接口请求也是不一样的,所以跨域了
+react
+常用的一些 hooks
+useEffect 和 useLayoutEffect 的区别?谁先执行?谁后执行?
+react 使用 虚拟 dom 的好处?为什么会提高性能?
-react
+直接操作 dom 性能是最高的。
-常用的一些hooks
+react diff 的原理
-useEffect 和 useLayoutEffect 的区别?谁先执行?谁后执行?
+## Promise 解决了什么问题
-react 使用 虚拟 dom 的好处?为什么会提高性能?
+Promise 的出现最重要的是为了统一 JS 中的异步实现方案
-直接操作dom性能是最高的。
+异步是 JS 中的常见场景,统一实现方案,不仅可以有效降低心智负担,更重要的是可以让不同的异步场景相互联动
-react diff 的原理
+Promise 也无法消除回调地狱,它只不过通过链式调用的方式让回调变得可控
+
+## 什么是 Vue 的响应式
+
+vue 数据响应式设计的初衷是为了实现数据和函数的联动,当数据变化时,用到该数据的联动函数会自动重新运行
+
+具体在 vue 的开发中,数据和组件的 render 函数关联在一起,从而实现了数据变化自动运行 render,在感官上就看到了组件的重新渲染。
+除了 vue 自动关联的 render 函数,其他还有很多使用到 vue 响应式的场景,比如 computed、watch 等等,不能仅把 vue 的数据响应式想象成和 render 的关联