类别:js / 日期:2023-05-11 / 浏览:526 / 评论:0

一个不考虑其他数据类型的公共方法,基本满足大部分场景


function deepCopy(target, cache = new Set()) {
  if (typeof target !== "object" || cache.has(target)) {
    return target;
  }
  if (Array.isArray(target)) {
    target.map((t) => {
      cache.add(t);
      return t;
    });
  } else {
    return [...Object.keys(target), ...Object.getOwnPropertySymbols(target)].reduce(
      (res, key) => {
        cache.add(target[key]);
        res[key] = deepCopy(target[key], cache);
        return res;
      },
      target.constructor !== Object
        ? Object.create(target.constructor.prototype)
        : {}
    );
  }
}
主要问题是
symbol 作为 key,不会被遍历到,所以 stringify 和 parse 是不行的
有环引用,stringify 和 parse 也会报错我们另外用 getOwnPropertySymbols 可以获取 symbol key 可以解决问题 1,用集合记忆曾经遍历过的对象可以解决问题 2。当然,还有很多数据类型要独立去拷贝。比如拷贝一个 RegExp,lodash 是最全的数据类型拷贝了,有空可以研究一下

另外,如果不考虑用 symbol 做 key,还有两种黑科技深拷贝,可以解决环引用的问题,比 stringify 和 parse 优雅强一些


function deepCopyByHistory(target) {
  const prev = history.state;
  history.replaceState(target, document.title);
  const res = history.state;
  history.replaceState(prev, document.title);
  return res;
}
async function deepCopyByMessageChannel(target) {
  return new Promise((resolve) => {
    const channel = new MessageChannel();
    channel.port2.onmessage = (ev) => resolve(ev.data);
    channel.port1.postMessage(target);
  }).then((data) => data);
}
无论哪种方法,它们都有一个共性:失去了继承关系,所以剩下的需要我们手动补上去了,故有 Object.create(target.constructor.prototype)的操作



版权声明 : 本文未使用任何知识共享协议授权,您可以任何形式自由转载或使用。

 可能感兴趣的文章

评论区

发表评论 / 取消回复

必填

选填

选填

◎欢迎讨论,请在这里发表您的看法及观点。

«    2023年11月    »
12345
6789101112
13141516171819
20212223242526
27282930

最新留言