Skip to content

Commit

Permalink
fix:修改
Browse files Browse the repository at this point in the history
  • Loading branch information
joywins-y committed Apr 6, 2024
1 parent 7d621e6 commit c50d3af
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 108 deletions.
15 changes: 14 additions & 1 deletion docs/面试复盘/2024年4月1号.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,19 @@

## 5. get 和 post 的区别

### 协议层面

语义上的区别

get 从服务器上获取数据
post 向服务器传递数据

### 应用层面

GET 的请求体为空,即请求体是空字符串(没有请求体是违反 http 协议的,所以 get 的请求体是空字符串,而不是没有)

### 浏览器层面

- get 在浏览器回退时是无害的,而 post 会再次发送请求,get 请求可以直接在浏览器中访问,支持刷新和后退,而 post 不能直接在浏览器访问,刷新后数据要重新发送。

- get 产生的 url 地址可以被标记(Bookmark),而 post 不可以
Expand Down Expand Up @@ -376,5 +389,5 @@ const onChange = (e) => {
setValue(e.target.value);
};

<input value={value} onChange={onChange} />
<input value={value} onChange={onChange} />;
```
201 changes: 94 additions & 107 deletions docs/面试复盘/第一版面试题.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 的区别:

Expand All @@ -26,8 +26,6 @@ typeof 和 instanceof 的区别:

精确性:typeof 对基本数据类型判断比较精确,对于引用类型则无法进一步区分。instanceof 可以准确的判断引用类型。



# 防抖和节流

## 防抖
Expand All @@ -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);
};
};
```

## 节流
Expand All @@ -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)
Expand All @@ -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}
```

Expand All @@ -103,37 +103,35 @@ 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);
```

## 递归复制

```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 用于标记需要序列化的属性,接受数组和函数类型

Expand All @@ -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));
Expand All @@ -158,112 +156,101 @@ 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 请求上。

生成机制

1. 服务端生成,在 Http Response Header 中 Set-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 的关联

0 comments on commit c50d3af

Please sign in to comment.