function debounce(fn, delay) {
let timer;
return function () {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.apply(this, arguments);
}, delay);
};
}
function throttle(fn, wait) {
let lastTime = 0;
return function (...args) {
const now = Date.now();
if (now - lastTime >= wait) {
fn.apply(this, args);
lastTime = now;
}
};
}
function unique(arr) {
return [...new Set(arr)];
}
function flatten(arr) {
return arr?.flat(Infinity);
}
function randomArr(arr) {
return arr.sort(() => 0.5 - Math.random());
}
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 值
function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
}
另一种实现方法
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;
}
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn(...args);
} else {
return (...nextArgs) => curried(...args, ...nextArgs);
}
};
}
// 数据
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;
}
function treeToList(tree, parentId = null, result = []) {
tree.forEach((node) => {
const { id, name, children } = node;
result.push({ id, name, parentId });
if (children && children.length) {
treeToList(children, id, result);
}
});
return result;
}
// 示例数据
const treeData = [
{
id: 1,
name: "A",
children: [
{
id: 2,
name: "B",
children: [
{ id: 4, name: "D", children: [] },
{ id: 5, name: "E", children: [] },
],
},
{
id: 3,
name: "C",
children: [{ id: 6, name: "F", children: [] }],
},
],
},
];
console.log(JSON.stringify(treeToList(treeData), null, 2));
Promise A+ 规范核心
- Promise 具有 then 方法,并支持 链式调用。
- then 方法接收两个参数(onFulfilled 和 onRejected)。
- Promise 必须是 异步执行(基于 setTimeout 实现 microtask)。
- Promise 支持 状态管理,包括:
- pending(等待)
- fulfilled(成功)
- rejected(失败)
- 状态 一旦改变,不可逆。
- then 必须返回一个新的 Promise,支持 值传递、异常处理、嵌套 Promise 解析。
class MyPromise {
constructor(executor) {
this.state = "pending"; // 初始状态
this.value = undefined; // 成功返回值
this.reason = undefined; // 失败原因
this.onFulfilledCallbacks = []; // 存储成功回调
this.onRejectedCallbacks = []; // 存储失败回调
const resolve = (value) => {
if (this.state === "pending") {
setTimeout(() => {
// 确保异步执行
this.state = "fulfilled";
this.value = value;
this.onFulfilledCallbacks.forEach((callback) => callback(value));
});
}
};
const reject = (reason) => {
if (this.state === "pending") {
setTimeout(() => {
this.state = "rejected";
this.reason = reason;
this.onRejectedCallbacks.forEach((callback) => callback(reason));
});
}
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
// 处理 onFulfilled/onRejected 为空的情况
onFulfilled =
typeof onFulfilled === "function" ? onFulfilled : (value) => value;
onRejected =
typeof onRejected === "function"
? onRejected
: (reason) => {
throw reason;
};
return new MyPromise((resolve, reject) => {
const handle = (callback, value, resolver) => {
try {
const result = callback(value);
if (result instanceof MyPromise) {
result.then(resolve, reject); // 递归解析 Promise
} else {
resolve(result);
}
} catch (error) {
reject(error);
}
};
if (this.state === "fulfilled") {
setTimeout(() => handle(onFulfilled, this.value, resolve));
} else if (this.state === "rejected") {
setTimeout(() => handle(onRejected, this.reason, reject));
} else {
this.onFulfilledCallbacks.push(() =>
handle(onFulfilled, this.value, resolve)
);
this.onRejectedCallbacks.push(() =>
handle(onRejected, this.reason, reject)
);
}
});
}
catch(onRejected) {
return this.then(null, onRejected);
}
finally(callback) {
return this.then(
(value) => MyPromise.resolve(callback()).then(() => value),
(reason) =>
MyPromise.resolve(callback()).then(() => {
throw reason;
})
);
}
// 静态 resolve
static resolve(value) {
return new MyPromise((resolve) => resolve(value));
}
// 静态 reject
static reject(reason) {
return new MyPromise((_, reject) => reject(reason));
}
// 静态 all
static all(promises) {
return new MyPromise((resolve, reject) => {
let count = 0;
const results = [];
promises.forEach((promise, index) => {
MyPromise.resolve(promise).then((value) => {
results[index] = value;
if (++count === promises.length) resolve(results);
}, reject);
});
});
}
// 静态 race
static race(promises) {
return new MyPromise((resolve, reject) => {
promises.forEach((promise) =>
MyPromise.resolve(promise).then(resolve, reject)
);
});
}
}
Function.prototype.myCall = function (context, ...args) {
context = context || globalThis;
context["fn"] = this;
const result = context["fn"](...args);
delete context["fn"];
return result;
};
Function.prototype.myApply = function (context, args) {
context = context || globalThis;
context["fn"] = this;
const result = context["fn"](...args);
delete context["fn"];
return result;
};
Function.prototype.myBind = function (context, ...args) {
return (...newArgs) => this.apply(context, [...args, ...newArgs]);
};
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__;
}
}
function myNew(fun, ...args) {
let obj = {};
obj.__proto__ = fun.prototype;
let res = fun.apply(obj, args);
return res instanceof Object ? res : obj;
}
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;
}
function sleep(delay) {
return new Promise((resolve) => setTimeout(resolve, delay));
}
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("任务队列已启动");
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
class LazyManClass {
constructor(name) {
this.name = name;
this.tasks = [];
// 任务队列初始化时,先插入 sayHi 任务
this.tasks.push(() => {
console.log(`Hi, I am ${this.name}`);
this.next();
});
// 确保任务开始执行
setTimeout(() => this.next(), 0);
}
// 执行下一个任务
next() {
if (this.tasks.length > 0) {
const task = this.tasks.shift();
task();
}
}
// 吃饭任务
eat(food) {
this.tasks.push(() => {
console.log(`Eating ${food}`);
this.next();
});
return this;
}
// 睡眠任务
sleep(time) {
this.tasks.push(() => {
setTimeout(() => {
console.log(`Wake up after ${time} seconds`);
this.next();
}, time * 1000);
});
return this;
}
// 优先睡眠(插入到任务队列最前面)
sleepFirst(time) {
this.tasks.unshift(() => {
setTimeout(() => {
console.log(`Wake up after ${time} seconds`);
this.next();
}, time * 1000);
});
return this;
}
}
// 包装成函数,返回 LazyManClass 实例
function LazyMan(name) {
return new LazyManClass(name);
}
// 测试用例
LazyMan("Tony").eat("breakfast").sleep(2).eat("lunch");
LazyMan("Tony").sleepFirst(2).eat("lunch");
function mySetinterval(fn, delay) {
let timer;
function loop() {
timer = window.setTimeout(() => {
fn();
loop();
}, delay);
}
loop();
return {
clear: () => clearTimeout(timer),
};
}
function compose(...fns) {
return function (initialValue) {
return fns.reduceRight((acc, fn) => fn(acc), initialValue);
};
}
function intersection(arr1, arr2) {
return [...new Set(arr1)].filter((item) => arr2.includes(item));
}
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;
});
}
function toArray(arrayLike) {
return Array.from(arrayLike);
}
函数记忆化(Memoization) 是一种优化技术,主要用于缓存函数的计算结果,避免重复计算,提升性能。适用于纯函数(相同输入始终返回相同输出)。
function memoize(fn) {
const cache = new Map(); // 存储计算结果
return function (...args) {
const key = JSON.stringify(args); // 用参数序列化作为缓存键
if (cache.has(key)) {
console.log("Fetching from cache:", key);
return cache.get(key);
}
console.log("Computing result:", key);
const result = fn(...args);
cache.set(key, result);
return result;
};
}
在 JavaScript 中,Promise.all 会并行执行所有异步任务,但如果任务量很大,会导致资源占用过高,因此需要限制并发数。
function limitConcurrency(tasks, limit) {
return new Promise((resolve, reject) => {
let index = 0; // 任务索引
let running = 0; // 当前运行中的任务数
const results = []; // 存储结果
function runNext() {
if (index >= tasks.length && running === 0) {
resolve(results); // 所有任务完成
return;
}
if (running >= limit || index >= tasks.length) return; // 达到并发限制
const taskIndex = index;
const task = tasks[index++];
running++;
task()
.then((result) => {
results[taskIndex] = result;
})
.catch((error) => {
results[taskIndex] = error; // 捕获错误,防止中断
})
.finally(() => {
running--;
runNext(); // 继续下一个任务
});
runNext(); // 继续分配任务
}
runNext(); // 启动任务
});
}
function getType(value) {
return Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
}