10 распространенных функций рукописного ввода во внешнем интерфейсе, знаете ли вы их все?

внешний интерфейс JavaScript
10 распространенных функций рукописного ввода во внешнем интерфейсе, знаете ли вы их все?

Десять тысяч высотных зданий чжан возвышаются над землей, а фундамент закален, так что мы можем навсегда остаться непобедимыми. Сегодня я представляю вам 10 распространенных функций рукописного ввода в JavaScript, а важные места прокомментированы. Что-то заимствовано у других, а что-то написано мной, если есть неточность, прошу меня поправить.

1. Защита от сотрясения

function debounce(fn, delay) {
  let timer
  return function (...args) {
    if (timer) {
      clearTimeout(timer)
    }
    timer = setTimeout(() => {
      fn.apply(this, args)
    }, delay)
  }
}

// 测试
function 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)
    }
  }
}

// 测试
function task() {
  console.log('run task')
}
const throttleTask = throttle(task, 1000)
window.addEventListener('scroll', throttleTask)

3. Глубокое копирование

function deepClone(obj, cache = new WeakMap()) {
  if (obj === null || typeof obj !== 'object') return obj
  if (obj instanceof Date) return new Date(obj)
  if (obj instanceof RegExp) return new RegExp(obj)
  
  if (cache.get(obj)) return cache.get(obj) // 如果出现循环引用,则返回缓存的对象,防止递归进入死循环
  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. Рукописные обещания

class MyPromise {
  constructor(executor) {
    this.status = 'pending' // 初始状态为等待
    this.value = null // 成功的值
    this.reason = null // 失败的原因
    this.onFulfilledCallbacks = [] // 成功的回调函数存放的数组
    this.onRejectedCallbacks = [] // 失败的回调函数存放的数组
    const resolve = value => {
      if (this.status === 'pending') {
        this.status = 'fulfilled'
        this.value = value;
        this.onFulfilledCallbacks.forEach(fn => fn()) // 调用成功的回调函数
      }
    }
    const reject = reason => {
      if (this.status === 'pending') {
        this.status = 'rejected'
        this.reason = reason
        this.onRejectedCallbacks.forEach(fn => fn()) // 调用失败的回调函数
      }
    };
    try {
      executor(resolve, reject)
    } catch (err) {
      reject(err)
    }
  }
  then(onFulfilled, onRejected) {
    // onFulfilled如果不是函数,则修改为函数,直接返回value
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
    // onRejected如果不是函数,则修改为函数,直接抛出错误
    onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err }
    const self = this
    return new MyPromise((resolve, reject) => {
      if (self.status === 'fulfilled') {
        setTimeout(() => {
          try {
            let x = onFulfilled(self.value);
            x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
          } catch (err) {
            reject(err)
          }
        })
      }
      if (self.status === 'rejected') {
        setTimeout(() => {
          try {
            let x = onRejected(self.reason)
            x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
          } catch (err) {
            reject(err)
          }
        })
      }
      if (self.status === 'pending') {
        self.onFulfilledCallbacks.push(() => { // 将成功的回调函数放入成功数组
          setTimeout(() => {
            let x = onFulfilled(self.value)
            x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
          })
        })
        self.onRejectedCallbacks.push(() => { // 将失败的回调函数放入失败数组
          setTimeout(() => {
            let x = onRejected(self.reason)
            x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
          })
        })
      }
    })
  }
}

// 测试
function p1() {
  return new MyPromise((resolve, reject) => {
    setTimeout(resolve, 1000, 1)
  })
}
function p2() {
  return new MyPromise((resolve, reject) => {
    setTimeout(resolve, 1000, 2)
  })
}
p1().then(res => {
  console.log(res) // 1
  return p2()
}).then(ret => {
  console.log(ret) // 2
})

5. Асинхронный контроль параллелизма

function limitRequest(urls = [], limit = 3) {
  return new Promise((resolve, reject) => {
    const len = urls.length
    let 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(['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')
}

// 测试
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()
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. Дедупликация массива

Установить дедупликацию

cosnt newArr = [...new Set(arr)] 

Массив из дедупликации

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
}

// 测试
const arr = [1, 1, 2, 3, 3]
console.log(resetArr(arr)) // [1, 2, 3]

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.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)

Выше приведены наиболее распространенные функции рукописного ввода в работе или поиске работы. Вы освоили их все? Добро пожаловать в поле для комментариев. Если статья была вам полезна, не забудьте поставить ценный лайк!

Я слышал, что людям, которым это нравится, не повезло, я верю, что вы будете первыми, кто получит повышение и прибавку к зарплате в наступающем году~😃