我正在使用一个将事物转换为 ES6 代理对象的库,以及另一个我认为令人窒息的库,因为我将其中一个传递给它(我的代码是一个讽刺,我知道),我无法弄清楚如何取消代理代理对象。
但我只是愚蠢。代理可以做任何事情!
我正在使用一个将事物转换为 ES6 代理对象的库,以及另一个我认为令人窒息的库,因为我将其中一个传递给它(我的代码是一个讽刺,我知道),我无法弄清楚如何取消代理代理对象。
但我只是愚蠢。代理可以做任何事情!
我发现了一个黑客。就我而言,我无法控制代理的创建(mobx 可观察值)。所以解决方案是:
JSON.parse(JSON.stringify(your.object))
尝试使用JSON.parse(JSON.stringify(proxyObj))
,但这会删除任何无法字符串化的内容(如类、函数、回调等),这对我的用例不利,因为我的对象中有一些回调函数声明,我希望将它们视为一部分我的对象。但是我发现使用Lodash cloneDeep函数在将 Proxy 对象转换为 POJO 并同时保持对象结构方面做得非常好。
convertProxyObjectToPojo(proxyObj) {
return _.cloneDeep(proxyObj);
}
使用扩展运算符怎么样?
const plainObject = { ...proxyObject };
pp = new Proxy(
{a:1},
{
get: function(target, prop, receiver) {
if(prop==='target') return target
}
}
)
但这只有在您可以控制代理的创建时才有效。事实证明它更容易:
pojo = Object.assign({}, proxyObj) // won't unwrap nested proxies though
对于可能喜欢这个答案的读者,大卫吉尔伯森的新答案可能会更好。我个人更喜欢 lodash clonedeep。最受欢迎的似乎是 JSON.parse(JSON.stringify(...))
谢谢@sigfried 的回答,这正是我想要的!
这是一个稍微更详细的版本,Symbol
用于避免与真实道具名称发生冲突。
const original = {foo: 'bar'};
const handler = {
get(target, prop) {
if (prop === Symbol.for('ORIGINAL')) return target;
return Reflect.get(target, prop);
}
};
const proxied = new Proxy(original, handler);
console.assert(original !== proxied);
const unproxied = proxied[Symbol.for('ORIGINAL')];
console.assert(original === unproxied);
通常你会为此使用 mobx util toJS() 。
import { observable, toJS } from "mobx";
const observed = observable({ foo: 'bar' })
const obj = toJS(observed)
在未代理的对象构造函数中,添加this.self=this
然后确保您的 get 处理程序允许self
返回属性并且您已准备就绪。 proxiedMyObj.self===myObj //returns true
假设您无权访问原始目标,将 a 转换为其值的最快方法Proxy
是将assign
其值转换为新的 plain Object
:
const obj = Object.assign({}, proxy);
或使用吊具:
const obj = { ...proxy };
例子
const user = {
firstName: 'John',
lastName: 'Doe',
email: 'john.doe@example.com',
};
const handler = {
get(target, property) {
return target[property];
}
};
const proxy = new Proxy(user, handler);
const a = Object.assign({}, proxy);
console.log(`Using Object.assign():`);
console.log(`Hello, ${a.firstName} ${a.lastName}!`);
console.log(JSON.stringify(a));
const s = { ...proxy };
console.log(`Using spreader:`);
console.log(`Hello, ${s.firstName} ${s.lastName}!`);
console.log(JSON.stringify(s));
如果不想使用 lodash object.assign({},val) 方法就可以了。但是如果 val 包含嵌套对象,它们将被代理。所以它必须像这样递归地完成:
function unproxify(val) {
if (val instanceof Array) return val.map(unproxify)
if (val instanceof Object) return Object.fromEntries(Object.entries(Object.assign({},val)).map(([k,v])=>[k,unproxify(v)]))
return val
}
实际上它是一个深度克隆功能。我认为如果 val 包含 Map 对象,它不起作用,但您可以按照相同的逻辑修改该函数。
如果你想取消代理 Vue3 代理,Vue3 提供了一个功能:toRaw