浅拷贝,简单深拷贝

浅拷贝

const _shallowClone = target => {
  let copy = Array.isArray(target) ? [] : {};
  for (let key in target) {
    if (target.hasOwnProperty(key)) {
      let value = target[key];
      copy[key] = value;
    }
  }
  return copy;
};

在这段代码中,我们定义了 _shallowClone 函数,它接受一个参数 target,表示要进行浅拷贝的目标对象。

首先,我们根据 target 的类型创建一个空的副本对象 copy。如果 target 是数组,则创建一个空数组作为
copy;否则,创建一个空对象。

然后,我们使用 for…in 循环遍历 target 对象的属性。对于每个属性,我们将其值赋给 value 变量,并将其复制到 copy
对象中的相应键名位置。

请注意,为了确保只拷贝 target 自身的属性,我们使用了 hasOwnProperty 方法进行检查。

最后,我们返回拷贝后的 copy 对象。

简单深拷贝

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

在这段代码中,我们定义了 _sampleDeepClone 函数,它接受一个参数 target,表示要进行简单深拷贝的目标对象。

首先,我们对 target 进行类型判断。如果 target 的类型不是对象或为 null,则直接返回 target,因为不需要进行拷贝。

然后,我们根据 target 的类型创建一个空的克隆对象 cloneTarget。如果 target 是数组,则创建一个空数组作为
cloneTarget;否则,创建一个空对象。

接下来,我们使用 for…in 循环遍历 target 对象的属性。对于每个属性,我们首先使用 hasOwnProperty
方法进行检查,确保只拷贝 target 自身的属性。

然后,我们判断当前属性值 target[key] 的类型。如果它是对象且不为 null,则递归调用 _sampleDeepClone
函数进行深拷贝,并将拷贝后的结果赋值给 cloneTarget[key]。否则,直接将属性值复制到 cloneTarget[key]。

最后,我们返回完成深拷贝的 cloneTarget 对象。

深拷贝

 if(target === null || typeof target !== 'object') return target
                const constructor = target.constructor
                if(/^(Function|Date|RegExp|Map|Set)$/i.test(constructor.name)) return new constructor(target)
                if(map.get(target)) return map.get(target)
                map.set(target, true)
                const clone = Array.isArray(target) ? [] : {}
                for(let key in target) {
                    if(Object.hasOwnProperty(key)) {
                        clone[key] = _completeDeepClone(target[key])
                    }
                }
                return clone

首先,我们进行了类型判断。如果 target 的类型为 null 或不是对象类型,直接返回 target,因为不需要进行深拷贝。

然后,我们获取 target 的构造函数,并使用正则表达式匹配构造函数的名称。如果构造函数的名称是
“Function”、“Date”、“RegExp”、“Map” 或 “Set”,则说明 target
是特殊类型的对象,直接通过构造函数创建一个新的实例,并将 target 作为参数传入,完成特殊对象的深拷贝。

接下来,我们使用 map 来检查是否已经拷贝过 target 对象。如果已经拷贝过,直接返回之前拷贝得到的对象。

然后,我们将 target 对象存入 map 中,标记为已拷贝。

接着,我们根据 target 的类型创建一个空的克隆对象 clone。如果 target 是数组,则创建一个空数组作为
clone;否则,创建一个空对象。

使用 for…in 循环遍历 target 对象的属性。对于每个属性,我们首先使用 hasOwnProperty
方法进行检查,确保只拷贝 target 自身的属性。

然后,我们递归调用 _completeDeepClone 函数对属性值进行深拷贝,并将拷贝后的结果赋值给 clone[key]。

最后,我们返回完成深拷贝的 clone 对象。

这个 _completeDeepClone 函数可以处理普通对象、数组以及特殊对象(如函数、日期、正则表达式、Map 和 Set)。它使用了
map 来解决循环引用问题,确保每个对象只被拷贝一次,避免出现无限递归的情况。

发布订阅模式

请补全JavaScript代码,完成"EventEmitter"类实现发布订阅模式。
注意:

  1. 同一名称事件可能有多个不同的执行函数
  2. 通过"on"函数添加事件
  3. 通过"emit"函数触发事件
   class EventEmitter {
  constructor() {
    this.events = {};
  }

  on(eventName, listener) {
    if (!this.events[eventName]) {
      this.events[eventName] = [];
    }
    this.events[eventName].push(listener);
  }

  emit(eventName, ...args) {
    const listeners = this.events[eventName];
    if (listeners) {
      listeners.forEach(listener => {
        listener.apply(null, args);
      });
    }
  }
}

在构造函数中,我们初始化一个空对象 “events”,用于存储事件和对应的监听函数。

“on” 方法用于添加事件和对应的监听函数。它接受两个参数:“eventName” 表示事件名称,“listener” 表示监听函数。如果
“events” 对象中不存在该事件名称的属性,则创建一个空数组,并将监听函数添加到数组中;否则,直接将监听函数添加到已存在的数组中。

“emit” 方法用于触发事件。它接受一个 “eventName” 参数和可选的其他参数。首先,我们从 “events” 对象中获取与
“eventName” 对应的监听函数数组。如果数组存在,则遍历数组,依次调用监听函数,并传入其他参数。

通过使用 “on” 方法添加事件和使用 “emit”
方法触发事件,我们可以实现简单的发布订阅模式。多个监听函数可以订阅同一个事件,当触发该事件时,所有订阅该事件的监听函数都会被执行,并传入相应的参数。

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值