笔记 防抖、节流、深拷贝、Promise

160 阅读2分钟

防抖

记得要用timer接收啊! 今天手写的时候没有写 timer = setTimeout(),setTimeout 的返回值 timeoutID 是一个正整数,表示定时器的编号。这个值可以传递给clearTimeout() 来取消该定时器。

function debounce(func, ms = 1000) {
    let timer; // 因为下一次调用debounceTask需要访问到timer,所以这里要返回一个闭包函数,携带之前的timer值
    return function (...args) {
        // 1.一律清除(判断是为了不清除第一次调用)
        if (timer) {
            clearTimeout(timer)
        }
        // 2.然后重新设置timer
        timer = setTimeout(() => {
            func.apply(this, args) // 注意:因为要传入参数所以才用了箭头函数,返回一个函数;如果不传参可以直接写成 timer = setTimeout(func, ms)
        }, ms)                
    }
}

// 测试
const task = () => { console.log('run task') }
const debounceTask = debounce(task, 1000)
window.addEventListener('scroll', debounceTask)

节流

function throttle(func, ms = 1000) {
  let canRun = true // 用一个变量记录是否正在等(和防止重复点击的思路很像)
  return function (...args) {
    if (!canRun) return
    canRun = false // 一进来就置为不能运行
    setTimeout(() => {
      func.apply(this, args)
      canRun = true // 计时器结束之后打开,置为可以运行
    }, ms)
  }
}

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

深拷贝

function deepCopy(obj, cache = new WeakMap()) {
  if (!obj instanceof Object) return obj
  // 防止循环引用
  if (cache.get(obj)) return cache.get(obj)
  // 支持函数
  if (obj instanceof Function) {
    return function () {
      return obj.apply(this, arguments)
    }
  }
  // 支持日期
  if (obj instanceof Date) return new Date(obj)
  // 支持正则对象
  if (obj instanceof RegExp) return new RegExp(obj.source, obj.flags)
  // 还可以增加其他对象,比如:Map, Set等,根据情况判断增加即可,面试点到为止就可以了

  // 数组是 key 为数字素银的特殊对象
  const res = Array.isArray(obj) ? [] : {}
  // 缓存 copy 的对象,用于处理循环引用的情况
  cache.set(obj, res)

  // 核心:遍历对象键值对:如果是对象,递归拷贝,如果不是对象直接拷贝
  Object.keys(obj).forEach((key) => {
    if (obj[key] instanceof Object) {
      res[key] = deepCopy(obj[key], cache)
    } else {
      res[key] = obj[key]
    }
  });
  return res
}

// 测试
const source = {
  name: 'Jack',
  meta: {
    age: 12,
    birth: new Date('1997-10-10'),
    ary: [1, 2, { a: 1 }],
    say() {
      console.log('Hello');
    }
  }
}
source.source = source
const newObj = deepCopy(source)
console.log(newObj.meta.ary[2] === source.meta.ary[2]); // false
console.log(newObj.meta.birth === source.meta.birth); // false

简陋方式:用json的内置方法

function deepClone(source) {
  return JSON.parse(JSON.stringify(source));
}