5

function.apply() を介して別のページで関数を呼び出そうとすると、IE で奇妙な動作が見られます。

簡単なテストケースを次に示します。

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>

firefox と chrome では、すべてのメソッドが適切に機能します。

IE (6、7、および 8 でテスト済み) では、applyArgs() メソッドと remoteApply() メソッドを除くすべてが期待どおりに機能します。

applyArgs() が apply を呼び出そうとすると、「JScript オブジェクトが必要です」というエラーが発生します (test1.html の 11 行目)。

remoteApply() は、apply を呼び出そうとすると、同じ「JScript オブジェクトが必要です」というエラーを返します (test2.html の 5 行目)。

問題は、apply() を使用できるようにする必要があることです。remoteApplyCopy() メカニズムなどを実行することで問題を回避できますが、それを回避しようとしています。apply() が機能しないのはなぜですか?

4

4 に答える 4

6

各ウィンドウには独自の配列コンストラクターがあるため、他のウィンドウで配列を作成する必要があります。これでうまくいくと思います。

この関数を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

なぜこれが機能するのかわかりませんが、私はあなたのコードをいじって、1つの解決策に出くわしました... 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

"... applyArgs() は、apply を呼び出そうとすると、"JScript object expected" エラーを返します (test1.html 行 11)。 remoteApply() は、apply を呼び出そうとすると、同じ "JScript object expected" エラーを返します (test2.html 行5)…」

「期待される」「JScriptオブジェクト」ではない正確なオブジェクトはどれですか?

(ヒント: デバッガーを使用してください)

--DBJ

于 2009-09-28T08:10:59.067 に答える
0

test2.html testApply() 関数を次のように変更すると:

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

remoteApply() は機能します。しかし、applyArgs() はまだ失敗しました。

于 2009-07-09T17:39:19.553 に答える