MessageChannel实现深拷贝

273 阅读1分钟

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

  • 会忽略undefined
  • 不能序列化函数
  • 性能差,根据网上的数据大概比遍历慢几倍
  • 无法实现对函数 、RegExp等特殊对象的克隆
  • 会抛弃对象的constructor,所有的构造函数会指向Object
  • 对象有循环引用,会报错
  • 含有symbol属性名的对象拷贝会漏掉symbol属性
const obj = {
    //fun: function name(params) {...},
    //name:undefined,
    //reg:/abc/
}

console.log(obj);// { fun: [Function: name] }
console.log(obj);// { name: undefined }
console.log(obj);// { name: /abc/ }
const temp = JSON.parse(JSON.stringify(obj))
console.log(temp);// {}

递归

// 递归
function deepClone(obj) {
    const objectMap = new Map()
    const _deepClone = (value) => {
        const type = typeof value
        if (type !== 'object' || type === null) {
            return value
        }
        if (objectMap.has(value)) {
            return objectMap.get(value)
        }
        const result = Array.isArray(value) ? [] : {}
        objectMap.set(value, result)
        for (const key in value) {
            result[key] = _deepClone(value[key])
        }
        return result
    }
    return _deepClone(obj)
}

MessageChannel 介绍:MessageChannel创建了一个通信的管道,这个管道有两个端口,每个端口都可以通过postMessage方法发送数据,另一个端口只要调用onmessage方法,就可以接收从另一个端口传过来的数据。如

// MessageChannel
const obj = { a: 1, b: 2 }
function deepClone(obj) {
    return new Promise((resolve) => {
        const { port1, port2 } = new MessageChannel() // 实例化了一个 channel 对象
        port1.postMessage(obj)  // 通过postMessage方法把数据传递
        port2.onmessage = msg => { // 通过onmessage方法监听事件接收到信息
            resolve(msg.data)
        }
    })
}
deepClone(obj).then(res => {
    console.log(res) // 
})