使用原型、类、以及访问器克隆对象时的注意事项


【Considerations when cloning objects with prototypes, classes, and accessors】

由于对象克隆使用 HTML 结构化克隆算法,因此不可枚举属性、属性访问器和对象原型都不会被保留。特别是,<Buffer> 对象在接收端会被读取为普通的 <Uint8Array>,而 JavaScript 类的实例会被克隆为普通的 JavaScript 对象。

【Because object cloning uses the HTML structured clone algorithm, non-enumerable properties, property accessors, and object prototypes are not preserved. In particular, <Buffer> objects will be read as plain <Uint8Array>s on the receiving side, and instances of JavaScript classes will be cloned as plain JavaScript objects.】

const b = Symbol('b');

class Foo {
  #a = 1;
  constructor() {
    this[b] = 2;
    this.c = 3;
  }

  get d() { return 4; }
}

const { port1, port2 } = new MessageChannel();

port1.onmessage = ({ data }) => console.log(data);

port2.postMessage(new Foo());

// Prints: { c: 3 } 

此限制适用于许多内置对象,例如全局的 URL 对象:

【This limitation extends to many built-in objects, such as the global URL object:】

const { port1, port2 } = new MessageChannel();

port1.onmessage = ({ data }) => console.log(data);

port2.postMessage(new URL('https://example.org'));

// Prints: { }