2009-07-09 66 views
5

我在IE中看到一些奇怪的行爲,試圖通過function.apply()調用另一個頁面中的函數。爲什麼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> 

在火狐和Chrome的所有方法的正常工作。

在IE(測試6,7和8)中,除了applyArgs()和remoteApply()方法外,其他所有方法都按預期工作。

applyArgs()在嘗試調用apply(test1.html第11行)時會給出一個「JScript對象預期」錯誤。

remoteApply()在嘗試調用apply(test2.html第5行)時給出了相同的「JScript對象預期」錯誤。

問題是,我需要能夠使用apply()。我可以通過做類似remoteApplyCopy()的機制來解決問題,但我試圖避免這種情況。爲什麼不適用()只是工作?

+0

如果最終複製參數到一個數組中,這裏是一個較短的方法:`var a = Array.prototype.slice.call(arguments,0);` – Blixt 2009-07-10 08:45:31

+0

我嘗試使用切片做args.slice(),但得到了同樣的錯誤。儘管試過了Array.prototype – Herms 2009-07-10 13:39:36

+0

另外,我想我必須在test2.html中這樣做,我試圖避免在目標頁面有任何額外的代碼所有(僅僅是被調用的實際功能)。 – Herms 2009-07-10 13:42:43

回答

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()函數。

0

我不知道爲什麼這個工作,但我是你的代碼玩弄和跨一個解決方案跌跌撞撞......把test1的內部測試2的功能,它的工作原理:

<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很奇怪)。就像我說的,我只是在玩弄代碼。

+0

是的,它看起來像問題是,數組在某種程度上失去了他們的數組類型信息時,頁面之間傳遞(這就是爲什麼remoteApply失敗,但remoteApplyCopy工程)。 – Herms 2009-07-09 15:09:14

0

如果更改test2.html testApply()函數如下:

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

remoteApply()的作品。但是,applyArgs()仍然失敗。

0

「... applyArgs()在嘗試調用apply(test1.html第11行)時會給出」JScript對象預期「錯誤。 remoteApply()在嘗試調用apply(test2.html第5行)時給出了相同的「JScript對象預期」錯誤。 ......」

哪個確切的對象不是 「JScript的對象」 的 「預期」

?(提示:使用調試器)

--DBJ

相關問題