Skip to content

Commit

Permalink
feat: add 0312
Browse files Browse the repository at this point in the history
  • Loading branch information
niaogege committed Mar 12, 2024
1 parent 85364ab commit cc32245
Show file tree
Hide file tree
Showing 26 changed files with 1,078 additions and 60 deletions.
4 changes: 2 additions & 2 deletions docs/interview/experiences/0index.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ nav:
### 如何防御 XSS 攻击

- 输入的内容进行过滤或者转译
- csp,配置安全内容策略白名单,告诉浏览器哪个域名下自由受信任
- csp,配置安全内容策略白名单,告诉浏览器**哪个域名**下自由受信任

### 简单说明 JS 运行机制

Expand All @@ -41,7 +41,7 @@ sessionStorage 属性允许你访问一个,对应当前源的 session `Storage

对面试官:多窗口之间 sessionStorage 不可以共享状态!!!但是在某些特定场景下新开的页面会复制之前页面的 sessionStorage!!也就是在**新标签或窗口**打开一个页面时会复制**顶级浏览会话的上下文作为新会话的上下文**

### preload 跟 prefetch 区别,都应用在什么场景下
### **preload****prefetch** 区别,都应用在什么场景下

```js
<link rel="preload" href="style.css" as="style">
Expand Down
5 changes: 5 additions & 0 deletions docs/interview/experiences/14202308handwriting.md
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,11 @@ function lazyLoadImg(imgs) {
const { target, intersectionRatio } = entry;
if (intersectionRatio > 0) {
target.src = target.dataset.src;
target.onerror = function (e) {
if (e.type === 'error') {
target.src = placeHoloder;
}
};
observer.unobserve(target);
}
});
Expand Down
39 changes: 36 additions & 3 deletions docs/interview/experiences/15202309handwriting.md
Original file line number Diff line number Diff line change
Expand Up @@ -853,7 +853,7 @@ isValid('<p>laoyao bye bye</p>');
// 示例用法
const array = [1, 2, 3, 4, 5]; // 4 5 1 2 3
const k = 2;
const rotatedArray = rotateArray(inputArray, k);
const rotatedArray = rotate(array, k);
console.log(rotatedArray); // 输出: [4, 5, 1, 2, 3]

// first 使用额外的数组
Expand Down Expand Up @@ -1083,6 +1083,8 @@ function shallow(obj1, obj2) {
}
return true;
}
// shallow({}, {});
shallow(NaN, NaN);
```

## 28.获取设备电池信息(**navigator.getBattery**)
Expand Down Expand Up @@ -1255,7 +1257,7 @@ function factorial(n) {
factorial(4);
```

## 34.FileReader 使用
## 34.FileReader 读写文件

```js
function uploadFile(file) {
Expand Down Expand Up @@ -1347,7 +1349,7 @@ trans(123456);

## 37.两个字符串对比, 得出结论都做了什么操作, 比如插入或者删除?

> form leetcode [编辑距离](https://leetcode.cn/problems/edit-distance/description/)
> from leetcode [编辑距离](https://leetcode.cn/problems/edit-distance/description/)
```js
pre = 'abcde123';
Expand Down Expand Up @@ -1749,6 +1751,37 @@ var compareVersion = function (v1, v2) {

## 49.【代码题】实现一个拼手气抢红包算法

```js
/**
* @param {number } money 总共发多少红包
* @param {number } count 红包个数
* @param {number } minBase 红包最少发多少
* @param {number } maxBase 红包最多不能超过平均的几倍
*/
function redPacket({ money, count, minBase = 0.1, maxBase = 2 }) {
let remainMoney = money;
let ans = [];
for (let i = 0; i < count - 1; i++) {
let max = (remainMoney / count) * maxBase; // 最多不能超过平均的2倍
let curMon = Math.random() * max;
curMon = curMon < minBase ? minBase : curMon;
curMon = Math.floor(curMon * 100) / 100;
remainMoney = Math.round((remainMoney - curMon) * 100) / 100;
ans.push(curMon);
}
// 最后一个剩余红包
ans.push(remainMoney);
console.log(
ans,
ans.reduce((a, b) => Number(a) + Number(b)),
);
}
redPacket({
money: 20,
count: 4,
}); //  [8.67, 3.73, 1.42, 6.18] 20
```

## 50. 数字转 36 进制

```js
Expand Down
42 changes: 42 additions & 0 deletions docs/interview/experiences/22leetcodeB.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,49 @@ houseRobber([1, 2, 3, 1]);
## [8.零钱兑换 I/II](https://leetcode.cn/problems/coin-change/)

```js
/**
给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。
计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。
你可以认为每种硬币的数量是无限的。
示例 1:
输入:coins = [1, 2, 5], amount = 11
输出:3
解释:11 = 5 + 5 + 1
*/
var coinChange = function (coins, amount) {
let dp = new Array(amount + 1).fill(Infinity);
dp[0] = 0;
for (let coin of coins) {
for (let j = coin; j <= amount; j++) {
dp[j] = Math.min(dp[j], dp[j - coin] + 1);
}
}
return dp[amount] == Infinity ? '-1' : dp[amount];
};
```

零钱兑换 II

```js
/**
输入:amount = 5, coins = [1, 2, 5]
输出:4
解释:有四种方式可以凑成总金额:
5=5
5=2+2+1
5=2+1+1+1
5=1+1+1+1+1
*/
var change = function (amount, coins) {
let dp = new Array(amount + 1).fill(0);
dp[0] = 1;
for (let coin of coins) {
for (let j = coin; j <= amount; j++) {
dp[j] += dp[j - coin];
}
}
return dp[amount];
};
```

## 9.[剑指 Offer 18. 删除链表的节点](https://leetcode.cn/problems/shan-chu-lian-biao-de-jie-dian-lcof/)
Expand Down
157 changes: 157 additions & 0 deletions docs/interview/experiences/26handwritingHooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ nav:

## 1.useUpdate

有的时候我们需要组件强制更新,这个时候就可以使用这个钩子:

```js
import { useCallback, useState } from 'react';

Expand All @@ -44,3 +46,158 @@ const useLatest = (value) => {
```

## 3.useCreation

useCreation :是 useMemo 或 useRef 的替代品。换言之,useCreation 这个钩子增强了 useMemo 和 useRef,让这个钩子可以替换这两个钩子。(来自 ahooks-useCreation)

- useMemo 的值不一定是最新的值,但 useCreation 可以保证拿到的值一定是最新的值
- 对于复杂常量的创建,useRef 容易出现潜在的的性能隐患,但 useCreation 可以避免

```ts
import { useRef } from 'react';
import type { DependencyList } from 'react';

const depsAreSame = (oldDeps: DependencyList, deps: DependencyList): boolean => {
if (oldDeps === deps) return true;
for (let i = 0; i < oldDeps.length; i++) {
// 判断两个值是否是同一个值
if (!Object.is(oldDeps[i], deps[i])) return false;
}
return true;
};

const useCreation = (fn: () => any, deps: DependencyList) => {
const { current } = useRef({
deps,
obj: undefined as undefined,
initialized: false,
});
if (current.initialized === false || !depsAreSame(current.deps, deps)) {
current.deps = deps;
current.obj = fn();
current.initialized = true;
}
return current.obj;
};

export default useCreation;
```

## 4.useToggle

```js
import { useCallback, useState } from 'react';
const useToggle = (init) => {
const [toggle, setToggle] = useState(init);
const changeToggle = useCallback(() => {
setToggle((val) => !val);
}, []);
return [toggle, changeToggle];
};
```

## 5.useRequest

```ts
import { useState, useEffect } from 'react';
const useRequest = (url: string, options: any) => {
const [abort, setAbort] = useState(() => {});
const [res, setResponse] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const abortController = new AbortController();
const signal = abortController.signal;
setAbort(() => abortController.abort());
const res = await window.fetch(url, { ...options, signal, method: 'get' });
setResponse(res);
} catch (error) {
setError(error as any);
}
};
fetchData();
return () => {
if (typeof abort === 'function') {
abort();
}
};
}, []);
return {
res,
error,
abort,
};
};
export default useRequest;
```

## 6.useEventListener

```ts
import { useRef, useEffect } from 'react';

function useEventListener(eventName: string, handler: Function, element = window): void {
const saveHandler = useRef<Function>(() => {});
useEffect(() => {
saveHandler.current = handler;
}, [handler]);
useEffect(() => {
const isSupported = element && element.addEventListener;
if (!isSupported) return;
const eventListener = (event: Event) => saveHandler.current(event);
element.addEventListener(eventName, eventListener);
return () => {
element.removeEventListener(eventName, eventListener);
};
}, [eventName, element]);
}
export default useEventListener;
useEventListener('click', () => {});
```

## 7.useTimeout

useTimeout:一段时间内,执行一次

传递参数只要函数和延迟时间即可,需要注意的是卸载的时候将定时器清除下就 OK 了

```ts
import { useEffect } from 'react';
export const useTimeout = (fn: () => void, delay: number) => {
const fnRef = useLatest(fn);
useEffect(() => {
if (!delay || delay < 0) return;
const timer = setTimeout(() => {
fnRef && fnRef.current();
}, delay);
return () => {
clearTimeout(timer);
};
}, []);
};
```

## 8.useInterval

useInterval: 每过一段时间内一直执行

大体上与 useTimeout 一样,多了一个是否要首次渲染的参数 immediate

```ts
import { useEffect } from 'react';
export const useInterval = (fn: () => void, delay: number, immediate: boolean) => {
const fnRef = useLatest(fn);
useEffect(() => {
if (!delay || delay < 0) return;
if (immediate) {
fnRef.current();
}
const timer = setInterval(() => {
fnRef && fnRef.current();
}, delay);
return () => {
clearInterval(timer);
};
}, []);
};
```
23 changes: 22 additions & 1 deletion docs/interview/experiences/27handwritingTs.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ nav:
* 11.TS手写Unique 去重
* 12.OptionalKeys提取 T 中所有可选类型的 key 组成的联合类型。
* 13.NonOptionalKeys提取 T 中非所有可选类型的 key 组成的联合类型。
* 14.
* 14.如何限制数组索引为非负数
* 15.
*/
```
Expand Down Expand Up @@ -191,6 +191,16 @@ type Q031 = {
age: number;
};
type Q041 = OptionalKeys<Q03>;

type GetFunction<T> = {
[P in keyof T as T[P] extends Function ? P : never]: T[P];
};
type Q0311 = {
name?: string;
age: number;
getName: () => void;
};
type Q0312 = GetFunction<Q0311>;
```

## 13.NonOptionalKeys 提取 T 中非所有可选类型的 key 组成的联合类型。
Expand All @@ -205,3 +215,14 @@ type Q03 = {
};
type Q04 = NonOptionalKeys<Q03>;
```

## 14.如何限制数组索引为非负数

```ts
type NotNegative<N extends number> = `${N}` extends `-${number}` ? never : N;
function safeGet<T extends number>(arr: any[], index: NotNegative<T>) {
console.log(arr[index]);
}
// Argument of type 'number' is not assignable to parameter of type 'never'.ts(2345)
safeGet([1, 2, 3, 4], -1);
```
Loading

0 comments on commit cc32245

Please sign in to comment.