如何制作 Proxy 对象的结构化克隆?

ave*_*mia 23 javascript browser node.js vue.js

我正在使用 Vue3,其中很多对象都是用于反应性的代理对象。我想创建代理对象之一和最近发现的 StructuredClone 的深层副本。

https://developer.mozilla.org/en-US/docs/Web/API/structuredClone

当我运行以下代码时,在 proxyObj 上执行 StructuredClone 时出现错误:

const obj = {
    name: "Steve",
    age: 50
}
const handler = {}
const proxyObj = new Proxy(obj, {})

console.log(proxyObj)

const objCopy = structuredClone(obj)

console.log(objCopy)

const proxyObjCopy = structuredClone(proxyObj)
console.log(objCopy)

Run Code Online (Sandbox Code Playgroud)

未捕获的 DOMException:无法在“窗口”上执行“structedClone”:# 无法克隆。

有没有办法克隆代理对象?有没有办法我可以先取消引用它,复制它,而不失去反应性?任何帮助表示赞赏!

小智 6

如果你只是谈论 Vue3 并且没有嵌套代理,你可以toRaw直接使用:

import { reactive, toRaw } from 'vue';

const obj = reactive({ foo: 'bar' });

const objCopy = structuredClone(toRaw(obj)):
Run Code Online (Sandbox Code Playgroud)

在遇到过一些带有嵌套代理或代理数组等对象的情况后,我必须加倍努力并创建自己的toRawDeep.

由于它使用它应该与由、或所toRaw创建的代理一起使用。reactive()readonly()shallowReactive()shallowReadonly()

import { toRaw } from 'vue';

export function toRawDeep<T>(observed: T): T {
    const val = toRaw(observed);

    if (Array.isArray(val)) {
        return val.map(toRawDeep) as T;
    }

    if (val === null) return null as T;

    if (typeof val === 'object') {
        const entries = Object.entries(val).map(([key, val]) => [key, toRawDeep(val)]);

        return Object.fromEntries(entries);
    }

    return val;
}
Run Code Online (Sandbox Code Playgroud)


fp0*_*007 -1

Object.create按照您的示例,您可以使用和创建自己的函数Object.getOwnPropertyDescriptors

function cloneProxy(obj) {
    //creates a new object that inherits from the prototype of the original object
    const clone = Object.create(Object.getPrototypeOf(obj));
    const properties = Object.getOwnPropertyDescriptors(obj);
    
    for (prop in properties) {
        if (properties[prop].hasOwnProperty("value")) {
            clone[prop] = properties[prop].value;
        } else {
            clone[prop] = properties[prop];
        }
    }
    
    return clone;
}

const obj = {
    name: "Steve",
    age: 50
}
const handler = {}
const proxyObj = new Proxy(obj, {})
console.log(proxyObj) //{ name: 'Steve', age: 50 }

const objCopy = structuredClone(obj)
console.log(objCopy) //{ name: 'Steve', age: 50 }

const proxyObjCopy = cloneProxy(proxyObj)
console.log(proxyObjCopy) // { name: 'Steve', age: 50 }
Run Code Online (Sandbox Code Playgroud)

有关这些功能的更多信息:

Object.create--> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create

Object.getOwnPropertyDescriptors--> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptors