节流
function debounce(fn, delay) { let timer return function (...args) { if (timer) { clearTimeout(timer) } timer = setTimeout(() => { fn.apply(this, args) }, delay) }}// 测试const task = () => { console.log('run task')}const debounceTask = debounce(task, 1000)window.addEventListener('scroll', debounceTask)
防抖
function throttle(fn, delay) { let last = 0 // 上次触发工夫 return (...args) => { const now = Date.now() if (now - last > delay) { last = now fn.apply(this, args) } }}// 测试const task = () => { console.log('run task')}const throttleTask = throttle(task, 1000)window.addEventListener('scroll', throttleTask)
深拷贝
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
异步控制并发数
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'])