JS高级—19—防抖、节流、深拷贝、数组去重、事件总线;

一、防抖和节流

function debounce(time) {
  let timer
  return function () {
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => {
      console.log('helloWorld')
    }, time)
  }
}



function once(func) {
  let flag = false
  return function () {
    if (!flag) {
      flag = true
      func()
    }
  }
}
 

 

      function throttle(fn, interval, { immediate = true }) {

        let initDate = 0;

        return function () {
          let date = new Date().getTime();
          if (initDate === 0 && !immediate) initDate = date;
          if (date - initDate >= interval) {
            fn();
            initDate = date;

          } 
        };
      }

 

防抖:不断的对要触发的行为做延迟;

节流:限制行为次数;按照固定频率触发;

总的来说:都是对用户行为

 

点击事件后,等待超过单位时间才会执行回调函数;

点击事件后,等待一定单位时间(等待期间不管点击多少次都抛弃),触发一次;

 

 

 

 

 

 

 

 

 

 

二、深拷贝

 

 

简单的数据,我们可以使用

JSON.parse(JSON.stringify(obj)来进行,
如果有复杂数据肯定不行,因为JSON对undefined、symbol键、symbol值、function、set、map都不能进行处理;
所以,我们还是要写一个自己的深拷贝函数;

 

 

// const weakMap = new WeakMap() //解决对象的循环引用;

export function deepClone(originValue, weakMap = new WeakMap()) {
  //使用在函数参数中定义weakmap,而不在全局中定义weakmap,这样可以避免每次调用deepclone时都往weakmap里插入数据,导致后期的weakmap将会成为一个非常的数据;
  const toString = Object.prototype.toString;
  //   console.log(toString.call(originValue), originValue)
  //1.传进来一个基本数据类型
  if (toString.call(originValue) === '[object String]') return originValue;
  if (toString.call(originValue) === '[object Null]') return originValue;
  if (toString.call(originValue) === '[object Undefined]') return originValue;
  if (toString.call(originValue) === '[object Boolean]') return originValue;
  if (toString.call(originValue) === '[object Number]') return originValue;
  if (toString.call(originValue) === '[object Symbol]') return originValue;

  //2.引用数据类型object
  if (toString.call(originValue) === '[object Object]') {
    const newObj = {};
    //2.0循环引用问题
    if (weakMap.has(originValue)) return weakMap.get(originValue); //如果map中已经有了这个引用,则直接返回map里的这个值即可;
    weakMap.set(originValue, newObj);
    //2.1普通的key
    for (const key in originValue) {
      newObj[key] = deepClone(originValue[key], weakMap);
    }
    //2.2对Symbol的key进行特殊的处理
    const symbolKeys = Object.getOwnPropertySymbols(originValue);
    for (const sKey of symbolKeys) {
      // const newSKey = Symbol(sKey.description)
      newObj[sKey] = deepClone(originValue[sKey]);
    }

    return newObj;
  }
  //3.引用数据类型array
  if (toString.call(originValue) === '[object Array]') {
    return [...originValue];
  }
  //4.引用数据类型function
  if (toString.call(originValue) === '[object Function]') {
    //函数直接返回即可,不需要新建一个函数然后把所有的属性和方法都在添加一遍
    return originValue;
  }
  //5.引用数据类型set
  if (toString.call(originValue) === '[object Set]') {
    return new Set([...originValue]);
  }
  //6.引用数据类型map
  if (toString.call(originValue) === '[object Map]') {
    console.log(...originValue);
    return new Map([...originValue]);
  }

  //6.other
}

 

 

三、数组去重

第一个需求:数组里元素去重,遇到对象,如果对象所有属性一致则对象判定为重复的需要去重
第二个需求:数组里元素去重,遇到对象,如果对象的id一致就对象判定为重复的需要去重 

 

const arr = [1, 1, null, null, undefined, undefined, 'kobe', 'kobe', { id: 1, age: { name: 18 } }, { id: 1, age: { name: 18 } }, { age: 1, age: { name: 20 } }, [1, 2, 3], [1, 2, 3], true, true];
 

//1.需求:数组里元素去重,遇到对象,如果对象所有属性一致则对象判定为重复的需要去重;
//1.1使用set,基本数据类型都会被去重,但是引用数据类型不可去重(因为引用数据类型虽然内容一样,但是堆地址不一样故set认为不一样);
function removeDuplicate(oldArr) {
  console.log([...new Set(oldArr)]);
  return [...new Set(oldArr)];
}

[1,null,undefined,'kobe',true
{ id: 1, age: { name: 18 } },
{ id: 1, age: { name: 18 } },
{ age: { name: 20 } },
[ 1, 2, 3 ],
[ 1, 2, 3 ],
]

 
//1.2引用类型也去重
function removeDuplicate(oldArr) {
const newArr = oldArr.map((item) => JSON.stringify(item));
console.log([...new Set(newArr)]);
return [...new Set(newArr)].map((item) => {
if (item === undefined) return undefined; //edge-case:undefind无法Json.parse;
return JSON.parse(item);
});
}


[
1,null,undefined,'kobe',true,
{ id: 1, age: { name: 18 } },
{ age: { name: 20 } },
[ 1, 2, 3 ],
]

 

const arr = [1, 1, null, null, undefined, undefined, 'kobe', 'kobe', { id: 1, age: { name: 18 } }, { id: 1, age: { name: 18 } }, { age: 1, age: { name: 20 } }, [1, 2, 3], [1, 2, 3], true, true];

//2.需求:数组里元素去重,遇到对象,如果对象id一致则对象判定为重复的需要去重;
/**
 * 数组的元素有很多不同的类型,不同的类型使用不同的去重办法;
 * 去重前:将基本数据类型、引用数据类型之数组、引用数据类型之对象,都放到不同的数组里;baseOfArr,arrOfArr,objOfArr
 * 去重时:
 * 去重后:数组合并为新数组,最后返回;
 */
function removeDuplicate(oldArr) {
  let baseOfArr = [],
    arrOfArr = [];
  const objOfArr = [],
    obj = {},
    toString = Object.prototype.toString,
    baseDataType = ['[object Null]', '[object Undefined]', '[object Boolean]', '[object Number]', '[object Symbol]', '[object String]'];

  for (let i = 0; i < oldArr.length; i++) {
    // 如果是基本数据类型
    if (baseDataType.includes(toString.call(oldArr[i]))) baseOfArr.push(oldArr[i]);

    // 如果是引用数据类型之数组
    if (toString.call(oldArr[i]) === '[object Array]') arrOfArr.push(oldArr[i]);

    // 如果是引用数据类型之对象
    if (toString.call(oldArr[i]) === '[object Object]') {
      if (!obj[oldArr[i].id]) {
        objOfArr.push(oldArr[i]); //obj['id'] = undefined;
        obj[oldArr[i].id] = true; //obj['id'] = true;
      }
    }
    // other case
    continue;
  }
  baseOfArr = [...new Set(baseOfArr)];
  arrOfArr = [...arrOfArr.map((item) => JSON.stringify(item))].map((item) => JSON.parse(item));
  // console.log(baseOfArr, arrOfArr, objOfArr);
  return [...baseOfArr, ...arrOfArr, ...objOfArr];
}

console.log(removeDuplicate(arr));

[1,null,undefined,'kobe',true,
[ 1, 2, 3 ],
[ 1, 2, 3 ],
{ id: 1, age: { name: 18 } },
{ age: { name: 20 } }
]






//1.obj改为用uniqIdArr.inclued()判断;
//2.if上用Json.stringify()提前判断,可以直接过滤出单个元素,然后直接加到数组里就是可以用的;不用在最后再给数据类型为数组的元素再去重一遍;
function removeDuplicate3(arr) {
const uniqArr = [];
const uniqIdArr = [];
arr.forEach((a) => {
if (Object.prototype.toString.call(a) === '[object Object]') {
if (!uniqIdArr.includes(a.id)) {
uniqArr.push(a);
uniqIdArr.push(a.id);
}
} else {
if (!uniqArr.some((ua) => JSON.stringify(ua) === JSON.stringify(a))) {
uniqArr.push(a);
}
}
});
return uniqArr;
}
 

 

 

四、事件总线

完整的可以看老师的github之hy-event-bus仓库;

 

posted @ 2022-05-21 21:01  Eric-Shen  阅读(98)  评论(0编辑  收藏  举报