跨窗口Javascript:有正确的方法吗?

时间:2010-01-20 23:02:17

标签: javascript firefox serialization internet-explorer-8 popup

问题

我正在尝试创建一个方法,将对象传递给弹出窗口中的类似方法。我无法控制目标方法中的代码或传入的对象。目标方法当前使用JSON.stringify尽可能地序列化对象,或instanceof Array

第一个问题是IE8中的一个错误(见下文)。第二个,也就是更基本的是,原语在不同的窗口中是不一样的:

w = open("http://google.com")
w.Array == Array               // returns false

在弹出窗口上覆盖可能传入的任何类,然后在调用之后恢复它们,但它确实很脆弱并且是一个维护问题。

将对象序列化为JSON,然后在窗口的上下文中解析它会触及下面的Firefox错误。

我也有点厌恶做对象的深层复制或使用new w.Object等解析JSON,因为它不觉得它应该那么复杂。

任何人都可以提出一个明智的方法来解决这个问题,还是我应该接受不能在窗口之间逐字传递对象?


IE bug

JSON.stringify在IE8中不适用于Windows。如果我将一个对象传递给弹出窗口,它会尝试序列化它,stringify将返回undefined。要查看此问题,请在IE8中打开脚本控制台并尝试:

w = open("http://google.com")
JSON.stringify(Object())          // returns "{}"
w.JSON.stringify(w.Object())      // returns "{}"

w.JSON.stringify(Object())        // returns "undefined" on IE8
JSON.stringify(w.Object())        // returns "undefined" on IE8
JSON.stringify([1, w.Object()])   // returns "[1,null]" on IE8

我尝试通过设置w.JSON = JSON来解决这个问题,但是正如最后一个测试所示,当你从两个窗口获得对象时会中断。

Firefox bug

似乎调用w.Object()在Firefox中创建对象实际上调用了window.Object()。调用w.JSON.parsew.eval时会遇到同样的错误。要查看此信息,请打开Firebug的控制台并尝试:

w = open("http://google.com")
new w.Object instanceof w.Object        // returns true

w.Object() instanceof w.Object          // returns false on Firefox 3.5
w.Object() instanceof Object            // returns true on Firefox 3.5
w.Object.call(w) instanceof Object      // returns true on Firefox 3.5
w.JSON.parse("{}") instanceof w.Object  // returns false on Firefox 3.5
w.JSON.parse("{}") instanceof Object    // returns true on Firefox 3.5
w.eval("[]") instanceof w.Array         // returns false on Firefox 3.5
w.eval("[]") instanceof Array           // returns true on Firefox 3.5
w.eval.call(w, "[]") instanceof Array   // returns true on Firefox 3.5

我能看到的唯一解决方法是自己解析JSON字符串。

4 个答案:

答案 0 :(得分:1)

对于它的价值,这就是我现在正在做的事情:

  • 确保在弹出窗口中加载了jquery-json
  • 对象进行字符串化
  • 调用w.$.evalJSON(str),正确绑定基元
  • 将该结果传递给弹出窗口中的方法

或者(如果jquery-json不可用),您可以将以下脚本注入目标:

<script type="text/javascript">
function parseJSON(j) {
  return JSON.parse(j)
}
</script>

因为它将捕获弹出窗口的JSON,而不是调用者的。

任何更好的解决方案都很高兴。

答案 1 :(得分:1)

如果您尝试进行跨域脚本编写,似乎JSONP似乎值得调查。

答案 2 :(得分:1)

我不能说我完全理解你的问题,但是有一个有趣的window.name黑客值得一试:http://www.sitepen.com/blog/2008/07/22/windowname-transport/(博客文章使用了dojo,当然,它可以用也是纯粹的JS)。它比JSONP更安全,易于实现,似乎适用于所有浏览器 基本上,它允许您在window.name变量中存储任何长度的任何数据。真棒的是这个变量在页面更改/刷新时没有被刷新/清除,所以通过巧妙地使用iframe可以获得简单安全的跨域传输:)

答案 3 :(得分:0)

  

要看到这一点,请打开Firebug的控制台   并尝试:

错误:&lt; stackoverflow&gt;的权限被拒绝从&lt; google&gt;获取属性Window.Object。 在除第一行之外的任何行:w = open(“http://google.com”) Firefox 3.5.7

想一想:您试图用任意网站打开新窗口并向其发送可用于js的数据。似乎太不安全了。