1、防抖
防抖限制多长时间执行一次,节流限制多长时间必须执行依次
适用范围 input框实时搜索 防抖
debounce限制多长时间才能执行一次,throttle限制多长时间必须执行一次,一个限制上限、一个限制下限
function debounce(func, delay) {let timeout = null;.//闭包return function(e) {if(timeout){clearTimeout(timeout)}var context = this, args = argumentstimeout = setTimeout(function(){func.apply(context, args);},delay)};};// 测试function task() {console.log('run task')}const debounceTask = debounce(task, 1000)window.addEventListener('scroll', debounceTask)
2、节流
适用范围在 比input, keyup更频繁触发的事件中,如resize, touchmove, mousemove, scroll。throttle 会强制函数以固定的速率执行。因此这个方法比较适合应用于动画相关的场景。
throttle(fn,delay){let valid = truereturn function() {if(!valid){return false}var context = this, args = argumentsvalid = falsesetTimeout(() => {fn.apply(context, args)valid = true;}, delay)}}/////function throttle(fn, delay) {let last = 0 // 上次触发时间return (...args) => {const now = Date.now()if (now - last > delay) {last = nowfn.apply(this, args)}}}// 测试function task() {console.log('run task')}const throttleTask = throttle(task, 1000)window.addEventListener('scroll', throttleTask)
3、深拷贝
function deeepClone(obj, cache = new WeakMap()) {if (typeof obj !== 'object') return objif (obj === null) return objif (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 = objconst newObj = deepClone(obj)console.log(newObj.address === obj.address)
4、Promise
class MyPromise {constructor(executor) { // executor执行器this.status = 'pending' // 等待状态this.value = null // 成功或失败的参数this.fulfilledCallbacks = [] // 成功的函数队列this.rejectedCallbacks = [] // 失败的函数队列const that = thisfunction resolve(value) { // 成功的方法if (that.status === 'pending') {that.status = 'resolved'that.value = valuethat.fulfilledCallbacks.forEach(myFn => myFn(that.value)) //执行回调方法}}function reject(value) { //失败的方法if (that.status === 'pending') {that.status = 'rejected'that.value = valuethat.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){return new Promise((resolve, reject)=>{const len = urls.lengthlet count = 0// 同时启动多个limit 数量的任务while(limit > 0){start()limit -= 1}function start(){const url = urls.shift()if(url) {axios.post(url).finally(()=>{if(count == len - 1){//完成最后一个任务resolve()}else {// 完成本任务 执行下一个任务count++start()}})}}})}limitRequest(urls, limit)// 可以批量请求数据,所有的URL地址在urls参数中// 同时可以通过max参数 控制请求的并发度// 当所有的请求结束后,需要执行callback回调function sendRequest(urls, max ,callback){if(!urls ||!max) returnif(urls.length === 0 ){if(callback) callback()return}let fetchArr = [],i =0;function toFetch(){if(i === urls.length ) return Promise.resolve()// 取出第i个url 放进fetch里面let one = fetch(urls[i++])// 存入并发数组fetchArr.push(one)// 执行完从并发数组删除one.then(res => {console.log(res)fetchArr.splice(fetchArr.indexOf(one), 1)})let p = Promise.resolve()// 当并行数量到达限制后 使用race 比较 第一个完成。然后在调用函数本身if(fetchArr.length >= max) p = Promise.race(fetchArr)return p.then(() => toFetch())}// 循环完数组,使用all 等待全部执行完后调用回调函数toFetch().then(()=> Promise.all(fetchArr)).then(()=> callback())}sendRequest(urls, max, callback)
6、寄生组合继承
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 = ChildChild.prototype.study = function() {console.log(this.name + "is studying");}let child = new Child('xiaoxiao', 16)console.log(child.name)child.eat()child.study()
7、排序
sort 排序
// 对数字排序const arr =[2,1]arr.sort((a,b) => a-b)// 对字母排序const arr = ['b', 'c', 'a', 'e', 'd']arr.sort()
冒泡排序
function bubbleSort(arr) {let len = arr.lengthfor (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 re(arr) {let num = []arr.forEach((item)=>{if(res.indexOf(item) === -1){res.push(item)}})return num}
9、url参数
URLSearchParams// 创建一个URLSearchParams实例const urlSearchParams = new URLSearchParams(window.location.search);// 把键值对列表转换为一个对象const params = Object.fromEntries(urlSearchParams.entries());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' }
10、发布者/订阅者
// 发布者订阅者模式class EventEmitter {constructor() {this.subs = Object.create(null)}// 订阅$on(eventType,handler) {this.subs[eventType] = this.subs[eventType] || []this.subs[eventType].push(handler)}// 发布$emit(eventType) {console.log(this.subs, 'subs')console.log(this.subs[eventType], 'event')if(this.subs[eventType]){this.subs[eventType].forEach(func => {func()});}}}let em =new EventEmitter();em.$on('event', () => {console.log('1号订阅')})em.$on('event', () => {console.log('2号也订阅')})setTimeout(()=>{em.$emit('event')},3000)
