我一直以为的深度复制就是这样:
* for…in循环
* 判断属性是否是自己的
* typeof结果为object
还要额外区分具体是普通对象、还是array、还是map…
* 函数、Error无法被深度复制
* 注意循环引用
* JSON API满足大部分需求
昨天看到某篇又是关于深度复制的文章,惯性思维告诉我,不就是深度复制么,写来写去有啥好写的。还好,看在作者是前端大佬的份上,倒是看他能不能把这份冷饭炒出鲜味来。这一看不得了,一个占据大篇幅的新概念冒了出来:结构化克隆算法
。
具体的介绍直接看MDN,我这里只搬运几种常见的使用结构化克隆方式实现深度拷贝的方法:
- MessageChannel
function structuralClone(obj) {
return new Promise(resolve => {
const {port1, port2} = new MessageChannel();
port2.onmessage = ev => resolve(ev.data);
port1.postMessage(obj);
});
}
const obj = /* ... */;
const clone = await structuralClone(obj);
特点:异步、兼容性ok
- History API
function structuralClone(obj) {
const oldState = history.state;
history.replaceState(obj, document.title);
const copy = history.state;
history.replaceState(oldState, document.title);
return copy;
}
const obj = /* ... */;
const clone = structuralClone(obj);
特点:Safari对replaceState调用的限制数量为 30 秒内 100 次。
- Notification API
function structuralClone(obj) {
return new Notification('', {data: obj, silent: true}).data;
}
const obj = /* ... */;
const clone = structuralClone(obj);
特点:简洁、兼容性不佳(safari全系列不支持)
当然,由于是whatwg提出的东西,nodejs是沾不上边的,这三个方法都只能用于浏览器端。