为什么function.apply()不能在IE中跨文档边界工作?

时间:2022-04-20 13:28:20

I'm seeing some strange behavior in IE trying to call functions in another page via function.apply().

我在IE中看到一些奇怪的行为,试图通过function.apply()调用另一个页面中的函数。

Here's a simple test case:

这是一个简单的测试用例:

test1.html:

<HTML>
<HEAD>
<script language="javascript" type="text/javascript">
  var opened = null;

  function applyNone() {
    opened.testFunc.apply(opened);
  }

  function applyArgs() {
    opened.testFunc.apply(opened, ["applied array"]);
  }

  function call() {
    opened.testFunc("called directly");
  }

  function remoteApply() {
    opened.testApply(["used remote apply"]);
  }

  function remoteApplyCopy() {
    opened.testApplyCopy(["used remote apply copy"]);
  }

  function openPopup() {
    opened = window.open("test2.html", "_blank");
  }
</script>
</HEAD>
<BODY>
  <a href="#" onclick="openPopup()">OPEN</a>
  <hr>
  <a href="#" onclick="applyNone()">applyNone</a>
  <a href="#" onclick="applyArgs()">applyArgs</a>
  <a href="#" onclick="call()">call</a>
  <a href="#" onclick="remoteApply()">remoteApply</a>
  <a href="#" onclick="remoteApplyCopy()">remoteApplyCopy</a>
</BODY>
</HTML>

test2.html:

<HTML>
<HEAD>
<script language="javascript" type="text/javascript">
  function testApply(args) {
    testFunc.apply(this, args);
  }

  function testApplyCopy(args) {
    var a = [];
    for(var i = 0; i < args.length; i++) {
      a.push(args[i]);
    }
    testFunc.apply(this, a);
  }

  function testFunc() {
    var s = "Got: ";
    for(var i = 0; i < arguments.length; i++) {
      s += arguments[i] + " ";
    }
    document.getElementById("output").innerHTML += s + "<BR>";
  }
</script>
</HEAD>
<BODY>
  Hi there
  <div id="output"/>
</BODY>
</HTML>

In firefox and chrome all methods work properly.

在firefox和chrome中,所有方法都能正常工作。

In IE (tested in 6, 7, and 8) all but the applyArgs() and remoteApply() methods work as expected.

在IE中(在6,7和8中测试),除了applyArgs()和remoteApply()方法之外,所有方法都按预期工作。

applyArgs() gives a "JScript object expected" error when it tries calling apply (test1.html line 11).

applyArgs()在尝试调用apply(test1.html第11行)时给出了“期望的JScript对象”错误。

remoteApply() gives the same "JScript object expected" error when it tries calling apply (test2.html line 5).

remoteApply()在尝试调用apply(test2.html第5行)时给出了相同的“JScript对象期望”错误。

Problem is, I need to be able to use apply(). I can get around the issue by doing something like the remoteApplyCopy() mechanism, but I'm trying to avoid that. Why doesn't apply() just work?

问题是,我需要能够使用apply()。我可以通过执行类似remoteApplyCopy()机制来解决这个问题,但我正试图避免这种情况。为什么不适用()只是工作?

4 个解决方案

#1


You need to have the arrays created in the other window, because each window has its own Array constructor. I think this will work.

您需要在另一个窗口中创建数组,因为每个窗口都有自己的Array构造函数。我认为这会奏效。

Add this function to test2.html:

将此函数添加到test2.html:

function getEmptyArray() {
    return new Array();
}

And this function to test1.html:

而这个函数要test1.html:

Array.prototype.cloneToRemote = function (win) {
    var newArray = win.getEmptyArray();
    for (var i = 0; i < this.length; i++)
    {
        newArray.push(this[i]);
    }
    return newArray;
}

Then do this:

然后这样做:

function applyArgs() {
    opened.testFunc.apply(opened, ["applied array"].cloneToRemote(opened));
}

Note, it seems like you should be able to do

请注意,您似乎应该可以这样做

var newArray = new win.Array();

within the test1.html cloneToRemote() function, but I couldn't make that work. If you could do that, you could get rid of the new getEmptyArray() function in test2.html.

在test1.html cloneToRemote()函数中,但我无法做到这一点。如果你能做到这一点,你可以摆脱test2.html中新的getEmptyArray()函数。

#2


I have no idea why this works, but I was playing around with your code and stumbled across one solution... put test2's functions inside of test1 and it works:

我不知道为什么会这样,但我正在玩你的代码并偶然发现一个解决方案...把test2的函数放在test1中并且它可以工作:

<HTML>
<HEAD>
<script language="javascript" type="text/javascript">
  var opened = null;

  function applyArgs() {
    testFunc.apply(opened, ["applied array"]);
  }

  function openPopup() {
    opened = window.open("test2.html", "_blank");
  }

  function testFunc() {
    var s = "Got: ";
    for(var i = 0; i < arguments.length; i++) {
      s += arguments[i] + " ";
    }
    this.document.getElementById("output").innerHTML += s + "<BR>";
  }
</script>
</HEAD>
<BODY>
  <a href="#" onclick="openPopup()">OPEN</a>
  <hr>
  <a href="#" onclick="applyArgs()">applyArgs</a>
</BODY>
</HTML>

I'll let you know if I can figure out any more (IE is weird like that). Like I said, I was just toying with the code.

如果我能弄明白的话,我会告诉你的(IE很奇怪)。就像我说的那样,我只是玩弄代码。

#3


If you change test2.html testApply() function as follows:

如果您更改test2.html testApply()函数,如下所示:

function testApply() {
    testFunc.apply(this, arguments);
}

remoteApply() works. But, applyArgs() still failed.

remoteApply()有效。但是,applyArgs()仍然失败。

#4


"... applyArgs() gives a "JScript object expected" error when it tries calling apply (test1.html line 11). remoteApply() gives the same "JScript object expected" error when it tries calling apply (test2.html line 5). ..."

“... applyArgs()在尝试调用apply(test1.html第11行)时给出了”JScript对象期望“错误.remoteApply()在尝试调用apply时给出了相同的”JScript对象期望“错误(test2.html line 5)......“

Which exact object is not "JScript object" as "expected" ?

哪个确切的对象不是“JScript对象”为“预期”?

(hint: use debugger)

(提示:使用调试器)

--DBJ

#1


You need to have the arrays created in the other window, because each window has its own Array constructor. I think this will work.

您需要在另一个窗口中创建数组,因为每个窗口都有自己的Array构造函数。我认为这会奏效。

Add this function to test2.html:

将此函数添加到test2.html:

function getEmptyArray() {
    return new Array();
}

And this function to test1.html:

而这个函数要test1.html:

Array.prototype.cloneToRemote = function (win) {
    var newArray = win.getEmptyArray();
    for (var i = 0; i < this.length; i++)
    {
        newArray.push(this[i]);
    }
    return newArray;
}

Then do this:

然后这样做:

function applyArgs() {
    opened.testFunc.apply(opened, ["applied array"].cloneToRemote(opened));
}

Note, it seems like you should be able to do

请注意,您似乎应该可以这样做

var newArray = new win.Array();

within the test1.html cloneToRemote() function, but I couldn't make that work. If you could do that, you could get rid of the new getEmptyArray() function in test2.html.

在test1.html cloneToRemote()函数中,但我无法做到这一点。如果你能做到这一点,你可以摆脱test2.html中新的getEmptyArray()函数。

#2


I have no idea why this works, but I was playing around with your code and stumbled across one solution... put test2's functions inside of test1 and it works:

我不知道为什么会这样,但我正在玩你的代码并偶然发现一个解决方案...把test2的函数放在test1中并且它可以工作:

<HTML>
<HEAD>
<script language="javascript" type="text/javascript">
  var opened = null;

  function applyArgs() {
    testFunc.apply(opened, ["applied array"]);
  }

  function openPopup() {
    opened = window.open("test2.html", "_blank");
  }

  function testFunc() {
    var s = "Got: ";
    for(var i = 0; i < arguments.length; i++) {
      s += arguments[i] + " ";
    }
    this.document.getElementById("output").innerHTML += s + "<BR>";
  }
</script>
</HEAD>
<BODY>
  <a href="#" onclick="openPopup()">OPEN</a>
  <hr>
  <a href="#" onclick="applyArgs()">applyArgs</a>
</BODY>
</HTML>

I'll let you know if I can figure out any more (IE is weird like that). Like I said, I was just toying with the code.

如果我能弄明白的话,我会告诉你的(IE很奇怪)。就像我说的那样,我只是玩弄代码。

#3


If you change test2.html testApply() function as follows:

如果您更改test2.html testApply()函数,如下所示:

function testApply() {
    testFunc.apply(this, arguments);
}

remoteApply() works. But, applyArgs() still failed.

remoteApply()有效。但是,applyArgs()仍然失败。

#4


"... applyArgs() gives a "JScript object expected" error when it tries calling apply (test1.html line 11). remoteApply() gives the same "JScript object expected" error when it tries calling apply (test2.html line 5). ..."

“... applyArgs()在尝试调用apply(test1.html第11行)时给出了”JScript对象期望“错误.remoteApply()在尝试调用apply时给出了相同的”JScript对象期望“错误(test2.html line 5)......“

Which exact object is not "JScript object" as "expected" ?

哪个确切的对象不是“JScript对象”为“预期”?

(hint: use debugger)

(提示:使用调试器)

--DBJ