js高级之手写代码总结

251 阅读5分钟

js高级之手写代码总结

前言(吐槽)

相信在准备面试的朋友们, 除了苦逼的朗读并背诵八股文之外, 还要去力扣去刷各种算法题吧 谁让各个互联网大厂就爱这一套呢, 不过说实话, 鄙人也发自内心的认为数据结构与算法真滴非常之超级重要, 所以呢我就替大家总结一些js高级中我们常用到的一些方法和函数咯

防抖节流

相信大家对于这两个函数是非常熟悉的, 从我们开始学习js开始, 到我们学了几百年js后, 在面试中出现的概率也非常之高, 接下来我就从最简单的实现然后一步步完善这两个函数吧!

防抖

    1. 基本实现
// fn: 目标函数, delay: 限制时间
function(fn, delay){
  // 1.用于记录上一次事件触发的timer
      let timer = null
​
      // 2.触发事件时执行的函数
      const _debounce = () => {
        // 2.1.如果有再次触发(更多次触发)事件, 那么取消上一次的事件
        if (timer) clearTimeout(timer)
​
        // 2.2.延迟去执行对应的fn函数(传入的回调函数)
        timer = setTimeout(() => {
          fn()
          timer = null // 执行过函数之后, 将timer重新置null
        }, delay);
      }
​
      // 返回一个新的函数
      return _debounce
}
    1. this和参数的绑定
function hydebounce(fn, delay) {
      // 1.用于记录上一次事件触发的timer
      let timer = null
​
      // 2.触发事件时执行的函数
      const _debounce = function(...args) {
        // 2.1.如果有再次触发(更多次触发)事件, 那么取消上一次的事件
        if (timer) clearTimeout(timer)
​
        // 2.2.延迟去执行对应的fn函数(传入的回调函数)
        timer = setTimeout(() => {
          fn.apply(this, args)
          timer = null // 执行过函数之后, 将timer重新置null
        }, delay);
      }
​
      // 返回一个新的函数
      return _debounce
    }
    1. 取消功能的实现
function hydebounce(fn, delay) {
      // 1.用于记录上一次事件触发的timer
      let timer = null
​
      // 2.触发事件时执行的函数
      const _debounce = function(...args) {
        // 2.1.如果有再次触发(更多次触发)事件, 那么取消上一次的事件
        if (timer) clearTimeout(timer)
​
        // 2.2.延迟去执行对应的fn函数(传入的回调函数)
        timer = setTimeout(() => {
          fn.apply(this, args)
          timer = null // 执行过函数之后, 将timer重新置null
        }, delay);
      }
​
      // 3.给_debounce绑定一个取消的函数
      _debounce.cancel = function() {
        if (timer) clearTimeout(timer)
      }
​
      // 返回一个新的函数
      return _debounce
    }
    1. 立即执行功能增加
function hydebounce(fn, delay, immediate = false) {
      // 1.用于记录上一次事件触发的timer
      let timer = null
      let isInvoke = false
​
      // 2.触发事件时执行的函数
      const _debounce = function(...args) {
        // 2.1.如果有再次触发(更多次触发)事件, 那么取消上一次的事件
        if (timer) clearTimeout(timer)
​
        // 第一次操作是不需要延迟
        if (immediate && !isInvoke) {
          fn.apply(this, args)
          isInvoke = true
          return
        }
​
        // 2.2.延迟去执行对应的fn函数(传入的回调函数)
        timer = setTimeout(() => {
          fn.apply(this, args)
          timer = null // 执行过函数之后, 将timer重新置null
          isInvoke = false
        }, delay);
      }
​
      // 3.给_debounce绑定一个取消的函数
      _debounce.cancel = function() {
        if (timer) clearTimeout(timer)
        timer = null
        isInvoke = false
      }
​
      // 返回一个新的函数
      return _debounce
    }
    1. 获取返回值(使用回调函数)
function hydebounce(fn, delay, immediate = false, resultCallback) {
      // 1.用于记录上一次事件触发的timer
      let timer = null
      let isInvoke = false
​
      // 2.触发事件时执行的函数
      const _debounce = function(...args) {
        return new Promise((resolve, reject) => {
          try {
            // 2.1.如果有再次触发(更多次触发)事件, 那么取消上一次的事件
            if (timer) clearTimeout(timer)
​
            // 第一次操作是不需要延迟
            let res = undefined
            if (immediate && !isInvoke) {
              res = fn.apply(this, args)
              if (resultCallback) resultCallback(res)
              resolve(res)
              isInvoke = true
              return
            }
​
            // 2.2.延迟去执行对应的fn函数(传入的回调函数)
            timer = setTimeout(() => {
              res = fn.apply(this, args)
              if (resultCallback) resultCallback(res)
              resolve(res)
              timer = null // 执行过函数之后, 将timer重新置null
              isInvoke = false
            }, delay);
          } catch (error) {
            reject(error)
          }
        })
      }
​
      // 3.给_debounce绑定一个取消的函数
      _debounce.cancel = function() {
        if (timer) clearTimeout(timer)
        timer = null
        isInvoke = false
      }
​
      // 返回一个新的函数
      return _debounce
    }

节流

    1. 基本实现
function hythrottle(fn, interval) {
      let startTime = 0
​
      const _throttle = function() {
        const nowTime = new Date().getTime()
        const waitTime = interval - (nowTime - startTime)
        if (waitTime <= 0) {
          fn()
          startTime = nowTime
        }
      }
​
      return _throttle
    }
    1. this和参数的绑定
function hythrottle(fn, interval) {
      let startTime = 0
​
      const _throttle = function(...args) {
        const nowTime = new Date().getTime()
        const waitTime = interval - (nowTime - startTime)
        if (waitTime <= 0) {
          fn.apply(this, args)
          startTime = nowTime
        }
      }
​
      return _throttle
    }
    1. 立即执行控制
function hythrottle(fn, interval, leading = true) {
      let startTime = 0
​
      const _throttle = function(...args) {
        // 1.获取当前时间
        const nowTime = new Date().getTime()
​
        // 对立即执行进行控制
        if (!leading && startTime === 0) {
          startTime = nowTime
        }
​
        // 2.计算需要等待的时间执行函数
        const waitTime = interval - (nowTime - startTime)
        if (waitTime <= 0) {
          fn.apply(this, args)
          startTime = nowTime
        }
      }
​
      return _throttle
    }
    1. 尾部执行控制
function hythrottle(fn, interval, { leading = true, trailing = false } = {}) {
      let startTime = 0
      let timer = null

      const _throttle = function(...args) {
        // 1.获取当前时间
        const nowTime = new Date().getTime()

        // 对立即执行进行控制
        if (!leading && startTime === 0) {
          startTime = nowTime
        }

        // 2.计算需要等待的时间执行函数
        const waitTime = interval - (nowTime - startTime)
        if (waitTime <= 0) {
          // console.log("执行操作fn")
          if (timer) clearTimeout(timer)
          fn.apply(this, args)
          startTime = nowTime
          timer = null
          return
        } 

        // 3.判断是否需要执行尾部
        if (trailing && !timer) {
          timer = setTimeout(() => {
            // console.log("执行timer")
            fn.apply(this, args)
            startTime = new Date().getTime()
            timer = null
          }, waitTime);
        }
      }

      return _throttle
    }
    1. 取消功能实现
function hythrottle(fn, interval, { leading = true, trailing = false } = {}) {
      let startTime = 0
      let timer = null

      const _throttle = function(...args) {
        // 1.获取当前时间
        const nowTime = new Date().getTime()

        // 对立即执行进行控制
        if (!leading && startTime === 0) {
          startTime = nowTime
        }

        // 2.计算需要等待的时间执行函数
        const waitTime = interval - (nowTime - startTime)
        if (waitTime <= 0) {
          // console.log("执行操作fn")
          if (timer) clearTimeout(timer)
          fn.apply(this, args)
          startTime = nowTime
          timer = null
          return
        } 

        // 3.判断是否需要执行尾部
        if (trailing && !timer) {
          timer = setTimeout(() => {
            // console.log("执行timer")
            fn.apply(this, args)
            startTime = new Date().getTime()
            timer = null
          }, waitTime);
        }
      }

      _throttle.cancel = function() {
        if (timer) clearTimeout(timer)
        startTime = 0
        timer = null
      }

      return _throttle
    }
    1. 获取返回值(回调函数)
function hythrottle(fn, interval, { leading = true, trailing = false } = {}) {
      let startTime = 0
      let timer = null

      const _throttle = function(...args) {
        return new Promise((resolve, reject) => {
          try {
             // 1.获取当前时间
            const nowTime = new Date().getTime()

            // 对立即执行进行控制
            if (!leading && startTime === 0) {
              startTime = nowTime
            }

            // 2.计算需要等待的时间执行函数
            const waitTime = interval - (nowTime - startTime)
            if (waitTime <= 0) {
              // console.log("执行操作fn")
              if (timer) clearTimeout(timer)
              const res = fn.apply(this, args)
              resolve(res)
              startTime = nowTime
              timer = null
              return
            } 

            // 3.判断是否需要执行尾部
            if (trailing && !timer) {
              timer = setTimeout(() => {
                // console.log("执行timer")
                const res = fn.apply(this, args)
                resolve(res)
                startTime = new Date().getTime()
                timer = null
              }, waitTime);
            }
          } catch (error) {
            reject(error)
          }
        })
      }

      _throttle.cancel = function() {
        if (timer) clearTimeout(timer)
        startTime = 0
        timer = null
      }

      return _throttle
    }

以上的优化在面试中遇见的概率比较低, 但是基础版本我相信每个前端人都是必须要掌握的

暂时先更新到这哦