类别: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)的操作
版权声明 : 本文未使用任何知识共享协议授权,您可以任何形式自由转载或使用。

发表评论 / 取消回复