1 2 3 4 5 6 7 8 9 10 11 12 13 14
function debounce(fn, delay) { let timer; return function (...args) { timer && clearTimeout(timer); timer = setTimeout(() => fn.apply(this, args), delay); }; } // 测试 function task(arg) { console.log("run task" + arg); } const debounceTask = debounce(task, 1000); window.addEventListener("scroll", () => debounceTask(11));
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
function throttle(fn, delay) { let last = 0; return function (...args) { const now = Date.now(); if (now - last < delay) return; last = now; fn.apply(this, args); }; } // 测试 function task() { console.log("run task"); } const throttleTask = throttle(task, 1000); window.addEventListener("scroll", throttleTask);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
function deepClone(obj, cache = new WeakMap()) { if (typeof obj !== "object") return obj; // 普通类型,直接返回 if (obj === null) return obj; if (cache.get(obj)) return cache.get(obj); // 防止循环引用,程序进入死循环 if (obj instanceof Date) return new Date(obj); if (obj instanceof RegExp) return new RegExp(obj); // 找到所属原型上的constructor,所属原型上的constructor指向当前对象的构造函数 let cloneObj = new obj.constructor(); cache.set(obj, cloneObj); // 缓存拷贝的对象,用于处理循环引用的情况 for (let key in obj) { if (obj.hasOwnProperty(key)) { cloneObj[key] = deepClone(obj[key], cache); // 递归拷贝 } } return cloneObj; } // 测试 const obj = { name: "Jack", address: { x: 100, y: 200 } }; obj.a = obj; // 循环引用 const newObj = deepClone(obj); console.log(newObj.address === obj.address); // false
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 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
class MyPromise { constructor(executor) { // executor执行器 this.status = "pending"; // 等待状态 this.value = null; // 成功或失败的参数 this.fulfilledCallbacks = []; // 成功的函数队列 this.rejectedCallbacks = []; // 失败的函数队列 const that = this; function resolve(value) { // 成功的方法 if (that.status === "pending") { that.status = "resolved"; that.value = value; that.fulfilledCallbacks.forEach((myFn) => myFn(that.value)); //执行回调方法 } } function reject(value) { //失败的方法 if (that.status === "pending") { that.status = "rejected"; that.value = value; that.rejectedCallbacks.forEach((myFn) => myFn(that.value)); //执行回调方法 } } try { executor(resolve, reject); } catch (err) { reject(err); } } then(onFulfilled, onRejected) { if (this.status === "pending") { // 等待状态,添加回调函数到成功的函数队列 this.fulfilledCallbacks.push(() => { onFulfilled(this.value); }); // 等待状态,添加回调函数到失败的函数队列 this.rejectedCallbacks.push(() => { onRejected(this.value); }); } if (this.status === "resolved") { // 支持同步调用 console.log("this", this); onFulfilled(this.value); } if (this.status === "rejected") { // 支持同步调用 onRejected(this.value); } } } // 测试 function fn() { return new MyPromise((resolve, reject) => { setTimeout(() => { if (Math.random() > 0.6) { resolve(1); } else { reject(2); } }, 1000); }); } fn().then( (res) => { console.log("res", res); // res 1 }, (err) => { console.log("err", err); // err 2 }, );
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
function limitRequest(urls = [], limit = 5) { return new Promise((resolve, reject) => { const len = urls.length; let count = 0; // 当前进行到第几个任务 const start = async () => { const url = urls.shift(); // 从数组中拿取第一个任务 if (url) { try { await axios.post(url); if (count == len - 1) { // 最后一个任务 resolve(); } else { count++; // 成功,启动下一个任务 start(); } } catch (e) { count++; // 失败,也启动下一个任务 start(); } } }; // 启动limit个任务 while (limit > 0) { start(); limit -= 1; } }); } // 测试 limitRequest(["http://xxa", "http://xxb", "http://xxc", "http://xxd", "http://xxe"]);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
function Parent(name) { this.name = name; } Parent.prototype.eat = function () { console.log(this.name + " is eating"); }; function Child(name, age) { Parent.call(this, name); this.age = age; } Child.prototype = Object.create(Parent.prototype); Child.prototype.constructor = Child; // 测试 let xm = new Child("xiaoming", 12); console.log(xm.name); // xiaoming console.log(xm.age); // 12 xm.eat(); // xiaoming is eating
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
class Parent { constructor(name) { this.name = name; } eat() { console.log(this.name + " is eating"); } } class Child extends Parent { constructor(name, age) { super(name); this.age = age; } } // 测试 let xm = new Child("xiaoming", 12); console.log(xm.name); // xiaoming console.log(xm.age); // 12 xm.eat(); // xiaoming is eating
1 2 3 4 5 6 7 8 9
// 对数字进行排序,简写 const arr = [3, 2, 4, 1, 5]; arr.sort((a, b) => a - b); console.log(arr); // [1, 2, 3, 4, 5] // 对字母进行排序,简写 const arr = ["b", "c", "a", "e", "d"]; arr.sort(); console.log(arr); // ['a', 'b', 'c', 'd', 'e']
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
function bubbleSort(arr) { let len = arr.length; for (let i = 0; i < len - 1; i++) { // 从第一个元素开始,比较相邻的两个元素,前者大就交换位置 for (let j = 0; j < len - 1 - i; j++) { if (arr[j] > arr[j + 1]) { let num = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = num; } } // 每次遍历结束,都能找到一个最大值,放在数组最后 } return arr; } //测试 console.log(bubbleSort([2, 3, 1, 5, 4])); // [1, 2, 3, 4, 5]
1 2
cosnt newArr = [...new Set(arr)]; const newArr = Array.from(new Set(arr));
1 2 3 4 5 6 7 8 9 10 11 12 13
function resetArr(arr) { let res = []; arr.forEach((item) => { if (res.indexOf(item) === -1) { res.push(item); } }); return res; } // 测试 const arr = [1, 1, 2, 3, 3]; console.log(resetArr(arr)); // [1, 2, 3]
1 2 3 4
// 创建一个URLSearchParams实例 const urlSearchParams = new URLSearchParams(window.location.search); // 把键值对列表转换为一个对象 const params = Object.fromEntries(urlSearchParams.entries());
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
function getParams(url) { const res = {}; if (url.includes("?")) { const str = url.split("?")[1]; const arr = str.split("&"); arr.forEach((item) => { const key = item.split("=")[0]; const val = item.split("=")[1]; res[key] = decodeURIComponent(val); // 解码 }); } return res; } // 测试 const user = getParams("http://www.baidu.com?user=%E9%98%BF%E9%A3%9E&age=16"); console.log(user); // { user: '阿飞', age: '16' }
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 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
class EventEmitter { constructor() { this.cache = {}; } on(name, fn) { if (this.cache[name]) { this.cache[name].push(fn); } else { this.cache[name] = [fn]; } } off(name, fn) { const tasks = this.cache[name]; if (tasks) { const index = tasks.findIndex((f) => f === fn || f.callback === fn); if (index >= 0) { tasks.splice(index, 1); } } } emit(name, once = false) { if (this.cache[name]) { // 创建副本,如果回调函数内继续注册相同事件,会造成死循环 const tasks = this.cache[name].slice(); for (let fn of tasks) { fn(); } if (once) { delete this.cache[name]; } } } } // 测试 const eventBus = new EventEmitter(); const task1 = () => { console.log("task1"); }; const task2 = () => { console.log("task2"); }; eventBus.on("task", task1); eventBus.on("task", task2); eventBus.off("task", task1); setTimeout(() => { eventBus.emit("task"); // task2 }, 1000);