如何将ES6代理变回普通对象(PO​​JO)?

Sig*_*ied 4 javascript ecmascript-6 es6-proxy

我正在使用一个将内容转换为ES6代理对象的库,而另一个我认为令人窒息的库是因为我将其中的一个传递给了我(我的代码是荒唐的,我知道),但我不知道如何取消代理对象。

但是我只是傻瓜。代理可以做任何事情!(在下面回答我的问题...)

Cyc*_*dge 14

使用Spread 运算符怎么样?

 const plainObject = { ...proxyObject };
Run Code Online (Sandbox Code Playgroud)

  • 不适用于嵌套的`Proxy`(它只是一个浅拷贝),要递归地复制/克隆**整个**对象,请使用[`_.cloneDeep()`](https://lodash.com/docs/4.17 .15#cloneDeep) (6认同)

ghi*_*ing 8

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

convertProxyObjectToPojo(proxyObj) {
  return _.cloneDeep(proxyObj);
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*ark 6

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

JSON.parse(JSON.stringify(your.object))
Run Code Online (Sandbox Code Playgroud)

  • 聪明:)有时候事情可以这么简单,谢谢! (2认同)
  • @Sigfried 好吧,正如接受的答案中所说,它正在丢失一些东西,但我猜最常见的情况是当你的对象中没有这些类型的属性时。我认为它只是作为一个调试工具是好的,至少我只是为了这个目的才使用它。JSON.stringify({ key: 未定义 }); JSON.stringify({ key: Symbol() }); JSON.stringify({ key: function(){} }); // 全部将被转换为“{}” (2认同)

Sig*_*ied 5

pp = new Proxy(
   {a:1},
   {
      get: function(target, prop, receiver) { 
             if(prop==='target') return target 
           }
   }
)
Run Code Online (Sandbox Code Playgroud)

但这只有在您可以控制代理的创建时才有效。但事实证明更容易:

pojo = Object.assign({}, proxyObj) // won't unwrap nested proxies though
Run Code Online (Sandbox Code Playgroud)

对于可能喜欢这个答案的读者来说,大卫·吉尔伯特森的新答案可能会更好。我个人更喜欢lodash clonedeep。最流行的似乎是 JSON.parse(JSON.stringify(...))

  • 如果“get”处理程序仍然存在,这会导致“{a: undefined}”而不是“{a: 1}”。否则, [`({...proxyObj})`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) 甚至更短。 (2认同)
  • 您的“get”处理程序需要一个“else”情况,以便它在非“target”属性上正常运行(即“Reflect.get”)。 (2认同)

Jav*_*ict 5

如果不想使用 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
}
Run Code Online (Sandbox Code Playgroud)

实际上它是一个深度克隆功能。我认为如果 val 包含 Map 对象,它不起作用,但您可以按照相同的逻辑修改该函数。

如果你想取消 Vue3 代理,Vue3 提供了一个函数:toRaw

  • 感谢您贡献答案。请您编辑您的答案以包含对您的代码的解释吗?这将帮助未来的读者更好地理解正在发生的事情,特别是那些刚接触该语言并难以理解这些概念的社区成员。当已经有一个被社区验证的公认答案时,这一点尤其重要。在什么条件下您的方法可能会受到青睐?您正在利用新功能吗? (2认同)