未捕获的DOM异常:无法在“Window”上执行“postMessage”:无法克隆对象。

121

我正在尝试进行呼叫

parent.postMessage(obj, 'whatever');

我在iframe内部并且收到了这个错误:Uncaught DOMException: Failed to execute 'postMessage' on 'Window': An object could not be cloned.


2
如果某些内容无法通过结构化克隆算法进行复制,那么这种情况经常发生。window.postMessage使用此算法。有关更多信息,请参见我的**答案,其中包含解决方案和详细说明为什么会发生这种情况**。 - Bharata
2个回答

201

原来我传递的对象有方法,这就是为什么错误消息会说“无法克隆对象”。

要解决这个问题,你可以执行以下操作:

obj = JSON.parse(JSON.stringify(obj));
parent.postMessage(obj, 'whatever');

13
好的,因为Mozilla说消息已经被序列化了,所以这很好知道:https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage 很合理它不知道如何序列化一个函数...... - jonobr1
4
你将对象传递给父级后,能否访问该对象上的方法? - Prakash Palnati
2
请注意,这样做会在循环中崩溃(应该由postMessage保留),而不是在函数中崩溃。 - Kaiido
1
在我的情况下,问题是由于在参数中传递了一个不存在的变量引起的。 - Daniel Santana
同时,我们不能将DOM对象传递给目标方,因为"这些对象的所有权已经转移到目标方,并且在发送方不再可用"。 - undefined
显示剩余3条评论

0
根据您要传递的数据,更精确的方法可能是使用与postMessage()兼容的简单数据结构。
由于postMessage无法序列化SetIterator,因此以下代码将引发错误。
let s = new Set();
parent.postMessage({s: s.values()}, '*');

以下内容将按预期工作,因为postMessage可以序列化Array:
let s = new Set();
parent.postMessage({s: [...s]}, '*');

这种方法更符合postMessage()的隐式序列化的意图。当您需要更复杂的数据结构或者不想过于费力地进行操作时,老牌的JSON.stringify/parse函数就能很好地胜任 ;)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接