10个常见的JavaScript函数的前端手写功能,

107 阅读2分钟

前言

如果觉得本文有帮助 记得点赞三连哦 十分感谢!

1.防抖

function debounce(fn, delay){
  let timer
  return function(...args){
    if(timer){
      clearTimeout(timer)
    }
    timer = setTimeout(()=>{
      fn.apply(this.args)
    },delay)
  }
}
// test
function task(){
  console.log('run task')
}
const debounceTask = debounce(task ,1000)
window.addEventListener('scroll',debounceTask)

2.节流

function throttle(fn,delay){
let last = 0
return (...arge) => {
  const now = Date.now()
  if(now - last > delay){
    last = now
    fn.apply(thi.args)
  }
 }
}
//test
function 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) // Prevent circular references, the program enters an infinite loop
  if(obj instanceof Date) return new Date(obj)
  if(obj instanceof RegExp) return new RegExp(obj)
// Find the constructor on the owning prototype, and the constructor on the owning prototype points to the constructor of the current object
  let cloneObj = new obj.constructor()
  cache.set(obj,cloneObj) // Cache copied objects, used to handle circular references
  for (let key in obj){
    if(obj.hasOwnProperty(key)){
      cloneObj[key] = deepClone(obj[key], cache)
    }
  }
  return cloneObj
}
// test
const obj = { name:'Jack', address: { x:100, y:200} }
obj.a = obj // circular reference
const new Obj = deepClone(obj)
console.log(newObj.address === obj.address) // false

4.Promise实现

class MyPromise {
  constructor(executor){ // executor excutor
    this.status = 'pending' // waiting status
    this.value = null // parameter of success or failure
    this.fulfilledCallbacks = [] // Successful function queue
    this.rejectedCallbacks = [] // Failed function queue
    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 === 'resolved') {
      onRejected(this.value)
    }
  }
}
// test
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)
  },
  err =>{
    console.log('err',err)
  }
)

5.异步控制并发数

function limitRequest(urls = [], limit = 3){
  return new Promise((resolve,reject)=>{
    const len = urls.length
    let count = 0
    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(['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 = Object.create(Parent.prototype)
Child.prototype.contructor = Child
Child.prototype.study = function(){
  console.log(this.name + 'is studying')
}
// test
let child = new Child('xiaoming',16)
console.log(child.name) // xiaoming
child.eat()
child.study() // xiaoming is studying

7.数组排序

//sort
//Sort the numbers,abbreviated
const arr = [3,2,4,1,5]
arr.sort((a,b) => a - b)
console.log(arr) // [1,2,3,4,5]
// Sort the letters, abbreviated
const arr = ['b','c','a','e','b']
arr.sort()
console.log(arr) // ['a','b','c','d','e']

//Bubble Sort
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
}
// test
console.log(bubbleSort([2,3,1,5,4])) // [1,2,3,4,5]

8.阵列去重

//设置重复数据删除
var newArr = [...new Set(arr)]
Array.from // 去重
const newArr = Array.from(new Set(arr))
//重复数据删除索引
function resetArr(arr){
  let res = []
  arr.forEach(item => {
    if(res.indexOf(item) === -1){
      res.push(item)
    }
  })
  return res
}
//test
const arr = [1,1,2,3,3]
console.log(resetArr(arr)) // [1,2,3]

9.获取url参数

URLSearchParams 方法

// Create an instance of URLSearchParams
const urlSearchParams = new URLSearchParams(window.location.seatch);
// Convert the list of key-value pairs into an object
const params = Object.fromEntries(urlSearchParams.entries());

split方法

function get Params(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
}
// test
const user = getParams('http://www.baidu.com?user=%E9%98%BF%E9%A3%9E&age=16')
console.log(user) // {user:'abor',age:'16'}

10.事件总线|发布和订阅模式

class EventEmitter {
  constructor(){
    this.cache = {}
  }
on(name,fn){
  if (this.cache[name]){
    this.cache[name].push(fu)
  } 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]
       }
     }
   }
 }
 // test
 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)