IE9中的JavaScript中的错误用于不同上下文的原型?

时间:2011-07-10 08:24:29

标签: javascript popup internet-explorer-9 prototype-programming

在IE9中,执行以下操作:

Array.prototype.$$isArray = true;
var popup = window.open( .... );
// later
var x = ['test'];
alert( x[0] );        // Shows "test"
alert( x.$$isArray ); // Shows "true"

在弹出式HTML中执行:

function test( x ) {
  alert( x[0] );        // Shows "test"
  alert( x.$$isArray ); // Shows "undefined"
)

为什么结果不同?这是IE中的错误吗?

2 个答案:

答案 0 :(得分:1)

不,这不是一个错误(至少不是在浏览器中),而且它不仅仅是IE。

浏览器显示的每个文档都有自己的全局环境,包括基本对象的原型。他们每个人都是空白。一个文档中的Array构造函数与另一个文档中的Array构造函数不同,并且这些构造函数不共享公共prototype属性;环境断开了。这就是instanceof在多文档Web应用程序中无法正常工作的原因。

考虑这个例子(live copy):

window.onload = function() {

  document.getElementById('theButton').onclick = function() {
    var wnd, start;

    display("Adding property to <code>Array.prototype</code>");
    Array.prototype.__foo = "bar";

    display("Testing property locally, <code>[].__foo = " +
            [].__foo +
           "</code>");

    display("Opening pop-up window");
    wnd = window.open("http://jsbin.com/omopaw/3");

    display("Waiting for window to load...");
    start = new Date().getTime();
    checkWindowLoad();

    function checkWindowLoad() {
      var a, b;

      if (typeof wnd.getArray === "undefined") {
        if (new Date().getTime() - start > 10000) {
          display("Error, 10 seconds and the window hasn't loaded");
        }
        else {
          setTimeout(checkWindowLoad, 10);
        }
        return;
      }

      display("Window loaded, getting array from it");
      a = wnd.getArray();
      display("<code>a</code> contents: " + a.join(", "));
      display("<code>a.__foo = " + a.__foo + "</code>");
      display("<code>a instanceof Array</code>? " +
              (a instanceof Array));
      display("<code>wnd.Array === Array</code>? " + 
              (wnd.Array === Array));

      display("Creating <code>b</code>");
      b = [3, 4, 5];
      display("<code>b.__foo = " + b.__foo + "</code>");
      display("Passing <code>b</code> to the popup, look there for the result.");
      wnd.callback(b);
    }
  };

  function display(msg) {
    var p = document.createElement('p');
    p.innerHTML = msg;
    document.body.appendChild(p);
  }

};

打开一个弹出窗口,然后从中检索一个数组。但是我们收到的数组是由不同的 Array对象构建的,而不是我们窗口中的对象,因此我们没有添加我们的 { {1}}。然后它创建一个 具有这些添加项的数组实例,并将其传递给弹出窗口,该弹出窗口正确地看到了添加内容(因为对象继续引用其原始原型):

主窗口中的输出:

  

将属性添加到Array.prototype   
在本地测试属性,Array.prototype   
打开弹出窗口   
等待窗口加载......   
窗口加载,从中获取数组   
[].__foo = bar内容:1,2,3   
a   
a.__foo = undefined?假   
a instanceof Array?假   
创建wnd.Array === Array   
b   
b.__foo = bar传递给弹出窗口,查看结果。

...并在弹出窗口中显示:

  

我是弹出窗口。   
收到b:3,4,5   
x

你会在IE上看到输出(我专门测试IE9,但它适用于IE7,我也确定其他人也适用)和其他浏览器。

两个不同窗口中的环境可以相互通信,但它们没有共享的全局变量;父窗口中的x.__foo = bar不会以任何方式由子窗口继承。

您在评论中说过,当您将数组从主窗口传递到子窗口时,添加内容会“消失”。 (你的代码中没有任何东西显示你这样做。)我们可以从上面看到,实际上,对象保持与原型的关系正确并且确实显示了添加内容,所以我怀疑(道歉) )这只是代码中的一个错误。

答案 1 :(得分:0)

在弹出窗口中执行的脚本具有不同的上下文,因此如果您在弹出窗口中尝试此操作:

Array === window.top.Array // false