5

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

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

测试1.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>

测试2.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>

在 Firefox 和 chrome 中,所有方法都可以正常工作。

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

applyArgs() 在尝试调用 apply 时给出“JScript object expected”错误(test1.html 第 11 行)。

remoteApply() 在尝试调用 apply 时给出相同的“JScript object expected”错误(test2.html 第 5 行)。

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

4

4 回答 4

6

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

将此函数添加到 test2.html:

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

而这个函数到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;
}

然后这样做:

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

请注意,您似乎应该能够做到

var newArray = new win.Array();

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

于 2009-07-24T19:02:11.067 回答
0

我不知道为什么会这样,但是我在玩弄您的代码并偶然发现了一个解决方案...将 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>

如果我能弄清楚,我会告诉你的(IE 很奇怪)。就像我说的,我只是在玩弄代码。

于 2009-07-09T14:51:30.563 回答
0

如果你改变 test2.html testApply() 函数如下:

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

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

于 2009-07-09T17:39:19.553 回答
0

“... applyArgs() 在尝试调用 apply 时给出“JScript object expected”错误(test1.html 第 11 行)。remoteApply() 在尝试调用 apply 时给出相同的“JScript object expected”错误(test2.html 行5)……”

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

(提示:使用调试器)

--DBJ

于 2009-09-28T08:10:59.067 回答