高频手撕代码考察
手写Promise.all()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37//接受一个数据(或可迭代对象)
//等所有 Promise 成功,返回一个新 Promise,结果是 按顺序 的结果数组。
//如果其中有一个失败(reject),立即返回 reject。
function promiseAll(promises) {
return new Promise((resolve, reject) => {
if (!Array.isArray(promises)) {
return reject(new TypeError("args not an array"));
}
let results = [];
let completed = 0;
promises.forEach((p, index) => {
Promise.resolve(p).then(value => {
results[index] = value;
completed++;
if (completed === promises.length) {
resolve(results);
}
}) catch (error => {
reject(error);
});
});
if (promises.length === 0) {
resolve([]);
}
});
}
const p1 = Promise.resolve(1);
const p2 = new Promise(res => setTimeout(() => res(2), 1000));
const p3 = 3;
promiseAll([p1, p2, p3])
.then(results => console.log("success:", results))
.catch(error => console.error("failed:", error));手撕防抖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20function debounce(fn, delay) {
let timer = null;
return function(...args) {
const context = this;
if(timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.apply(context, args);
}, delay);
};
}
function onResize() {
console.log("resize 事件触发:", new Date().toLocaleTimeString());
}
// 500ms 防抖
window.addEventListener("resize", debounce(onResize, 500));
- 在防抖函数里:
- context = this; 保存了外部调用时的 this(比如某个按钮 DOM 对象)。
- args = arguments(用扩展语法 …args 收集)保存了调用时传进来的参数。
- 当定时器触发时,如果直接写 fn():
- this 会丢失(定时器里的 this 默认是 window 或 undefined)。
- 参数也没法自动带过去。
- 所以要用 fn.apply(context, args):
- 保证 this 正确 → 就是调用 debounce 包裹函数时的 this。
- 保证参数不丢失 → args 是数组,apply 会把它展开传给 fn。
手撕new函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22function myNew(Constructor, ...args) {
// create null obj, let its __proto__ pointed to constructor's prototype
const obj = Object.create(Constructor.prototype);
// execute constructor, bind this to obj
const result = Constructor.apply(obj, args);
return (result !== null && (typeof result === 'object' || typeof result === 'function'))
? result
: obj;
}
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayHi() = function() {
console.log("Hi, I'm " + this.name);
};
const p1 = myNew(Person, 'Alice', 30);
p1.sayHi();手撕LRU,时间复杂度O(1)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24class LRUCache {
constructor(capacity) {
this.capacity = capacity;
this.map = new Map(); //有序表
}
get(key) {
if (!this.map.has(key)) return -1;
const value = this.map.get(key);
this.map.delete(key);
this.map.set(key, value);//放到队尾
return value;
}
put(key, value) {
if (this.map.has(key)) {
this.map.delete(key);
} else if (this.map.size >= this.capacity) {
const firstKey = this.map.keys().next().value;
this.map.delete(firsetKey);//找到并删除队首
}
this.map.set(key, value);
}
}