手写题
函数防抖
js
function debounce(fn, delay) {
let timer;
return function () {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.apply(this, arguments);
}, delay);
};
}
函数节流
js
function throttle(fn, wait) {
let lastTime = 0;
return function (...args) {
const now = Date.now();
if (now - lastTime >= wait) {
fn.apply(this, args);
lastTime = now;
}
};
}
数组去重
js
function unique(arr) {
return [...new Set(arr)];
}
数组拍平
js
function flatten(arr) {
return arr?.flat(Infinity);
}
数组乱序
js
function randomArr(arr) {
return arr.sort(() => 0.5 - Math.random());
}
手写发布订阅
ts
type Handler = () => void;
class PubSub {
private subscribers: Map<string, any>;
constructor() {
this.subscribers = new Map();
}
on(type: string, handler: Handler) {
const handlers = this.subscribers.get(type);
if (handlers) {
this.subscribers.set(type, [...handlers, handler]);
} else {
this.subscribers.set(type, [handler]);
}
}
off(type: string) {
const handlers = this.subscribers.get(type);
if (handlers) {
this.subscribers.delete(type);
}
}
emit(type: string, ...args: unknown[]) {
const handlers = this.subscribers.get(type);
if (handlers) {
handlers.forEach((h) => h(...args));
}
}
}
深拷贝
- 使用 JSON.parse 和 JSON.stringify 实现,但是会丢失 Function、underfind 和 null 值
js
function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
}
另一种实现方法
js
function deepClone(obj) {
if (obj === null || typeof obj !== "object") {
return obj;
}
let result = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (Object.hasOwnProperty.call(obj, key)) {
if (typeof obj[key] !== "object") {
result[key] = obj[key];
} else {
result[key] = deepClone(obj[key]);
}
}
}
return result;
}
函数柯里化
JSON 转 Tree
js
// 数据
const students = [
{ id: 1, name: "ming", parentId: 0 },
{ id: 2, name: "hua", parentId: 1 },
{ id: 3, name: "qin", parentId: 1 },
{ id: 4, name: "liu", parentId: 2 },
];
function jsonToTree(data) {
const map = new Map();
data.forEach((item) => map.set(item.id, { ...item, children: [] }));
let tree: any = [];
data.forEach((item) => {
if (item.parentId === 0) {
tree.push(map.get(item.id));
} else {
const parent = map.get(item.parentId);
if (parent) {
parent.children.push(map.get(item.id));
}
}
});
return tree;
}
Tree 转 json
实现 Promise
call&apply&bind
实现 call 方法
js
Function.prototype.myCall = function (context, ...args) {
context = context || globalThis;
context["fn"] = this;
const result = context["fn"](...args);
delete context["fn"];
return result;
};
实现 apply 方法
js
Function.prototype.myApply = function (context, args) {
context = context || globalThis;
context["fn"] = this;
const result = context["fn"](...args);
delete context["fn"];
return result;
};
实现 bind 方法
js
Function.prototype.myBind = function (context, ...args) {
return (...newArgs) => this.apply(context, [...args, ...newArgs]);
};
实现 instanceof 关键字
js
function myInstanceOf(left, right) {
let prototype = right.prototype;
left = left.__proto__;
while (true) {
if (!left) return false;
if (left == prototype) return true;
left = left.__proto__;
}
}
实现 new 关键字
js
function myNew(fun, ...args) {
let obj = {};
obj.__proto__ = fun.prototype;
let res = fun.apply(obj, args);
return res instanceof Object ? res : obj;
}
实现 Object.assign
js
function myAssign(target, ...sources) {
// 如果目标是 null 或 undefined,则抛出错误
if (target == null) {
throw new TypeError("Cannot convert undefined or null to object");
}
// 将 target 转换为对象
target = Object(target);
// 遍历每个源对象
for (let i = 0; i < sources.length; i++) {
const source = sources[i];
// 如果 source 不是 null 或 undefined,才进行属性复制
if (source != null) {
// 获取源对象的所有可枚举属性
for (let key of Object.keys(source)) {
target[key] = source[key];
}
// 处理 Symbol 属性(因为 Object.keys() 不会获取到 Symbol 属性)
if (Object.getOwnPropertySymbols) {
const symbols = Object.getOwnPropertySymbols(source);
for (let symbol of symbols) {
target[symbol] = source[symbol];
}
}
}
}
return target;
}
实现 sleep 方法
js
function sleep(delay) {
return new Promise((resolve) => setTimeout(resolve, delay));
}
任务队列
js
class TaskQueue {
constructor() {
this.queue = []; // 存储任务
this.running = false; // 是否正在执行任务
}
addTask(task) {
this.queue.push(task);
this.run(); // 每次添加任务后尝试执行
}
async run() {
if (this.running) return;
this.running = true;
while (this.queue.length > 0) {
const task = this.queue.shift();
await task(); // 任务是一个异步函数
}
this.running = false;
}
}
// 使用示例
const queue = new TaskQueue();
queue.addTask(
() =>
new Promise((res) =>
setTimeout(() => {
console.log("任务 1");
res();
}, 1000)
)
);
queue.addTask(
() =>
new Promise((res) =>
setTimeout(() => {
console.log("任务 2");
res();
}, 500)
)
);
queue.addTask(
() =>
new Promise((res) =>
setTimeout(() => {
console.log("任务 3");
res();
}, 800)
)
);
console.log("任务队列已启动");
尾递归非波拉切数列
js
function fibonacciTail(n, a = 0, b = 1) {
if (n === 0) return a;
if (n === 1) return b;
return fibonacciTail(n - 1, b, a + b);
}
// 测试
console.log(fibonacciTail(10)); // 55
console.log(fibonacciTail(50)); // 12586269025
实现 LazyMan
setTimout 实现 setInterval
js
function mySetinterval(fn, delay) {
let timer;
function loop() {
timer = window.setTimeout(() => {
fn();
loop();
}, delay);
}
loop();
return {
clear: () => clearTimeout(timer),
};
}
实现 compose 方法
js
function compose(...fns) {
return function (initialValue) {
return fns.reduceRight((acc, fn) => fn(acc), initialValue);
};
}
两个数组的交集
js
function intersection(arr1, arr2) {
return [...new Set(arr1)].filter((item) => arr2.includes(item));
}
实现对象数组去重
js
function uniqueById(arr, key) {
const map = new Map();
return arr.filter((item) => {
if (!map.has(item[key])) {
map.set(item[key], item);
return true;
}
return false;
});
}
实现类数组转换为数组方法
js
function toArray(arrayLike) {
return Array.from(arrayLike);
}
实现JS函数记忆
实现异步并发数限制
实现判断数据类型的方法
js
function getType(value) {
return Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
}