前端9个手写技巧 防抖 节流 去重 排序 es5继承 异步同步 深拷贝 实现prosimes
1、防抖
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)
2、节流
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)
3、深拷贝
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
4、实现prosime
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 })
5、异步控制并发函数
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'])
6、es5组合继承
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 = new Parent() // 原型链继承 Child.prototype.contructor = Child Child.prototype.study = function () { console.log(this.name + ' is studying') } // 测试 let child = new Child('xiaoming', 16) console.log(child.name) // xiaoming child.eat() // xiaoming is eating child.study() // xiaoming is studying
7、数组排序
// 对数字进行排序,简写 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((a, b) => { if (a > b) return 1 else if (a < b) return -1 else return 0 }) console.log(arr) // ['a', 'b', 'c', 'd', 'e']
冒泡
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]
8、数组去重
set
cosnt newArr = [...new Set(arr)]
Array.from
const newArr = Array.from(new Set(arr))
indexOf
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]
9、获取url参数
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' }
本文来自博客园,作者:玖捌,转载请注明原文链接:https://www.cnblogs.com/fyh0912/p/15739988.html
浙公网安备 33010602011771号