万丈高楼平地起,地基打的牢,能力永远立于不败之地。明天给大家带来的是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 (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、实现 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 = 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 = 3) {
return new Promise((resolve, reject) => {

const len = urls.lengthlet 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) {      if (count == len - 1) {        // 最初一个工作失败        resolve()      } else {        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 = 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、数组排序
sort 排序
// 对数字进行排序,简写
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、数组去重
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 参数
URLSearchParams 办法
// 创立一个URLSearchParams实例
const urlSearchParams = new URLSearchParams(window.location.search);
// 把键值对列表转换为一个对象
const params = Object.fromEntries(urlSearchParams.entries());
复制代码
split 办法
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...')
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)
复制代码
以上就是工作或求职中最常见的手写性能,你是不是全都把握了呢,欢送在评论区交换。如果文章对你有所帮忙,不要忘了点上贵重的一赞!

据说点赞的人运气都不差,置信来年第一个升职加薪的肯定是你~

最初
如果你感觉此文对你有一丁点帮忙,点个赞。或者能够退出我的开发交换群:1025263163互相学习,咱们会有业余的技术答疑解惑

如果你感觉这篇文章对你有点用的话,麻烦请给咱们的开源我的项目点点star: https://gitee.com/ZhongBangKe...不胜感激 !