18

我正在使用一个将事物转换为 ES6 代理对象的库,以及另一个我认为令人窒息的库,因为我将其中一个传递给它(我的代码是一个讽刺,我知道),我无法弄清楚如何取消代理代理对象。

但我只是愚蠢。代理可以做任何事情!

4

9 回答 9

18

我发现了一个黑客。就我而言,我无法控制代理的创建(mobx 可观察值)。所以解决方案是:

JSON.parse(JSON.stringify(your.object))
于 2019-01-31T13:22:53.003 回答
13

尝试使用JSON.parse(JSON.stringify(proxyObj)),但这会删除任何无法字符串化的内容(如类、函数、回调等),这对我的用例不利,因为我的对象中有一些回调函数声明,我希望将它们视为一部分我的对象。但是我发现使用Lodash cloneDeep函数在将 Proxy 对象转换为 POJO 并同时保持对象结构方面做得非常好。

convertProxyObjectToPojo(proxyObj) {
  return _.cloneDeep(proxyObj);
}
于 2020-02-21T19:06:07.667 回答
5

使用扩展运算符怎么样?

 const plainObject = { ...proxyObject };
于 2020-11-17T20:07:32.643 回答
4
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(...))

于 2018-11-01T13:51:53.167 回答
1

谢谢@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);
于 2020-03-13T10:29:16.440 回答
1

通常你会为此使用 mobx util toJS() 。

import { observable, toJS } from "mobx";

const observed = observable({ foo: 'bar' })

const obj = toJS(observed)
于 2020-11-07T01:11:39.937 回答
0

在未代理的对象构造函数中,添加this.self=this

然后确保您的 get 处理程序允许self返回属性并且您已准备就绪。 proxiedMyObj.self===myObj //returns true

于 2019-08-23T16:33:16.100 回答
0

假设您无权访问原始目标,将 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));

于 2021-09-09T12:07:23.727 回答
0

如果不想使用 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

于 2021-11-03T15:45:39.177 回答