什么❓你最怕手写❓带你专攻手写❗

113 阅读3分钟

👊 多看,多听,多读,多应用。

防抖 / 节流

防抖:

在事件被触发n秒后,再执行回调。

function debounce(fn, wait) {
  // 声明一个timer变量用于存储定时器ID,初始化为null
  var timer = null;

  // 返回一个新的函数(闭包)
  return function() {
    // 保存当前执行上下文(this)和参数(arguments)
    var context = this,
      args = arguments;

    // 检查是否已有定时器存在
    if (timer) {
      // 如果存在定时器,清除它(取消之前的等待执行)
      clearTimeout(timer);
      // 将timer重置为null
      timer = null;
    }

    // 设置一个新的定时器
    timer = setTimeout(() => {
      // 定时器回调:使用apply调用原始函数,保持正确的this和参数
      fn.apply(context, args);
    }, wait); // 等待wait毫秒后执行
  };
}

节流:

function throttle(fn, delay) {
  // 记录上一次执行的时间戳,初始化为当前时间
  var preTime = Date.now();

  // 返回一个新的函数(闭包)
  return function() {
    // 保存当前执行上下文(this)和参数(arguments)
    var context = this,
        args = arguments,
        // 获取当前时间戳
        nowTime = Date.now();

    // 检查当前时间与上次执行时间的间隔是否超过设定的延迟时间
    if (nowTime - preTime >= delay) {
      // 更新上次执行时间为当前时间
      preTime = Date.now();
      // 调用原始函数,并返回其结果
      return fn.apply(context, args);
    }
  };
}

深 / 浅 拷贝

1、object.assign 浅

Object.assign(target, ...sources)

比如:

let target = {};
let source = { a: { b: 1 } };
Object.assign(target, source);
console.log(target); // { a: { b : 1 } }

image.png

object.assign有缺点:
有两个不能拷贝:
1、对象继承属性、2、不可枚举属性

怎么讲,我们来看一个例子:

let obj1 = {
  a: {
    b: 1
  },
  
  sym: Symbol(1)
}

Object.defineProperty(obj1, 'innumerable', {
  value: '不可枚举',
  enumberable: false,
});

let obj2 = {};
Object.assign(obj2, obj1);
obj1.a.b = 2;

console.log('obj1', obj1);
console.log('obj2', obj2);

image.png

由上面例子可以知道,Symbol类型是可以通过Object.assign()去拷贝得到的。

2、扩展运算符 浅

let cloneObj = { ...obj };

object.assign一样,只能浅拷贝

3、concat拷贝数组 浅

let a = [1, 2, 3];
let b = a.concat();

b[1] = 4;

console.log(a); // [1, 2, 3]
console.log(b); // [1, 4, 3]

image.png

slice拷贝数组 浅

// slice要这样用:arr.slice(start, end)

let a = [1, 2, { val: 3 }];
let b = a.slice();

b[2].val = 100;

console.log(a); // [1, 2, { val: 100 }]

image.png

浅,只能拷一层对象,如果多层,浅拷贝就GG,而且它a会和被克隆成它的那个b,其实两者指向的是同一个地址,a变,b改,b改,a也会变。

那好,实现一下浅拷贝吧:

// 思路:两点。
// 一个点:基础类型 直给
// 另一个点:引用类型 就一层完事

const shallowClone = (target) => {
  if (typeof target === 'object' && target !== null) {
  
    const cloneTarget = Array.isArray(target) ? []: {};
    
    for (let prop in target) {
      if (target.hasOwnProperty(prop)) {
          cloneTarget[prop] = target[prop];
      }
    }
    
    return cloneTarget;
    
  } else {
    return target;
  }
}

浅指向同一块地址,那么深就是开一块新的内存地址。

JSON.stringify

let a = {
  name: 'kk',
  age: 18,
  jobs: {
    first: 'waiter',
    second: 'manager'
  }
}

let b = JSON.parse(JSON.stringify(a)) // JSON.parse 将 JSON 字符串生成一个新的对象

a.jobs.first = 'cleaner'
console.log(b.jobs.first) // waiter

image.png

JSON.stringify完美吗?

不。有缺点:

1、undefined、symbol 拷贝不过来,会被忽略掉;对象有NaNInfinity-InfinityJSON序列化会变成null
2、不能序列化函数
3、无法拷贝不可枚举的属性和对象的原型链
4、拷贝RegExp引用类型会变成空对象
5、拷贝Date会变成字符串
6、不能解决循环引用的对象,就是 对象成环 obj[key] = obj

手写

const isComplexDataType = obj => (typeof obj === 'object' || typeof obj === 'function') && (obj !== null)

const deepClone = function (obj, hash = new WeakMap()) {
  // Date
  if (obj.constructor === Date) {
    // 日期对象直接返回一个新的日期对象
    return new Date(obj)       
  }
  
  // 正则
  if (obj.constructor === RegExp){
    //正则对象直接返回一个新的正则对象
    return new RegExp(obj)     
  }
  
  //如果循环引用了就用 weakMap 来解决
  if (hash.has(obj)) {
    return hash.get(obj)
  }
  let allDesc = Object.getOwnPropertyDescriptors(obj)

  //遍历传入参数所有键的特性
  let cloneObj = Object.create(Object.getPrototypeOf(obj), allDesc)

  //继承原型链
  hash.set(obj, cloneObj)

  for (let key of Reflect.ownKeys(obj)) { 
    cloneObj[key] = (isComplexDataType(obj[key]) && typeof obj[key] !== 'function') ? deepClone(obj[key], hash) : obj[key]
  }
  
  return cloneObj
} 

lodash库

下工具库去用。

image.png

const _ = require('lodash');

const originalObj = {
  a: 1,
  b: {
    c: 2,
    d: [3, 4, 5]
  }
};

// 使用 cloneDeep 进行深拷贝
const clonedObj = _.cloneDeep(originalObj);

// 修改克隆后的对象不会影响原对象
clonedObj.b.c = 20;
console.log(originalObj.b.c); // 仍然是 2

充满热情,精力旺盛,I love my job! I love my job! I love my job! 👅
多阅读,多尝试。结合指导,运用于实际。