深拷贝之MessageChannel

1,796 阅读1分钟

这是我参与8月更文挑战的第1天

  • 我们先来了解下MessageChannel

定义

Channel Messaging API的**MessageChannel** 接口允许我们创建一个新的消息通道,并通过它的两个MessagePort 属性发送数据。

image.png

属性

MessageChannel.port1

返回channel的port1

MessageChannel.port2

返回channel的port2

构造函数

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

WeChate345edce18e634878b4ae9961718db49.png

消息通信

简单来说,MessageChannel创建了一个通信的管道,这个管道有两个端口,每个端口都可以通过postMessage发送数据,而一个端口只要绑定了onmessage回调方法,就可以接收从另一个端口传过来的数据。 简单例子

        const { port1, port2 } = new MessageChannel();
        port1.onmessage = function(event) {
            console.log("port1收到来自port2的数据:" + event.data);
        }
        port2.onmessage = function(event) {
            console.log("port2收到来自port1的数据:" + event.data);
        }

        port1.postMessage("发送给port2");
        port2.postMessage("发送给port1");

实现深拷贝

深拷贝通常使用JSON.parse(JSON.stringify(object))来实现, 但是该方法也是有局限性的:

  • 会忽略undefined
  • 会忽略symbol
  • 不能序列化函数
  • 不能解决循环引用的对象

如果你所需拷贝的对象含有内置类型并且不包含函数,可以使用 MessageChannel

function structuralClone(obj) { 
   return new Promise(resolve => { 
       const { port1, port2 } = new MessageChannel() 
       port2.onmessage = ev => resolve(ev.data)
       port1.postMessage(obj)
      }) 
    } 
var obj = { a: 1, b: { c: 2 } } 
obj.b.d = obj.b 
// 注意该方法是异步的 // 可以处理 undefined 和循环引用对象 
const test = async () => { 
    const clone = await structuralClone(obj) 
    console.log(clone) 
}
test()