结构化复制

我一直以为的深度复制就是这样:
* 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是沾不上边的,这三个方法都只能用于浏览器端。