簡體   English   中英

如何在父窗口創建的iframe的onload處理程序中獲取對iframe窗口對象的引用

[英]How to get a reference to an iframe's window object inside iframe's onload handler created from parent window

在我粘貼任何代碼之前,這是場景:

  1. 我有一個HTML文檔,使用JavaScript創建一個空的iframe
  2. JavaScript創建一個函數並將對該函數的引用附加到iframe的文檔對象(使用doc.open()來獲取對文檔的引用)
  3. 然后將該函數作為iframe文檔的onload處理程序附加(通過將<body onload="...">寫入iframe。

現在讓我難過的是onload處理程序中的全局(窗口)和文檔對象(在它運行時)與通過腳本節點添加的JavaScript運行的相同對象不同。

這是HTML:

<!doctype html>
<html>
<head>
<script>
(function(){
  var dom,doc,where,iframe;

  iframe = document.createElement('iframe');
  iframe.src="javascript:false";

  where = document.getElementsByTagName('script')[0];
  where.parentNode.insertBefore(iframe, where);

  doc = iframe.contentWindow.document;

  var _doc = document;

  doc.open()._l=function() {
    // the window object should be the one that doc is inside
    window.vanishing_global=new Date().getTime();

    var js = this.createElement("script");
    js.src = 'test-vanishing-global.js?' + window.vanishing_global;

    window.name="foobar";
    this.foobar="foobar:" + Math.random();
    document.foobar="barfoo:" + Math.random();

    // `this` should be the document object, but it's not
    console.log("this == document: %s", this == document);
    console.log("this == doc:      %s", this == doc);

    // the next two lines added based on @Ian's comment below
    console.log("_doc == document: %s", _doc == document);
    console.log("_doc == doc:      %s", _doc == doc);

    console.log("name: " + window.name + "\n" + "window.vanishing_global: " + window.vanishing_global + "\ntypeof window.vanishing_global: " + typeof window.vanishing_global + "\ndocument.foobar: " + document.foobar);
    this.body.appendChild(js);
  };
  doc.write('<body onload="document._l();"></body>');
  doc.close();
})();
</script>
</head>
<body>
</body>
</html>

這里是test-vanishing-global.js

console.log("name: " + window.name + "\n" + "window.vanishing_global: " + window.vanishing_global + "\ntypeof window.vanishing_global: " + typeof window.vanishing_global + "\ndocument.foobar: " + document.foobar);

說明:

將這兩個文件放入一個目錄中,然后在瀏覽器中打開HTML(在最新的Chrome和Firefox中測試,兩者都相同)。

這是我得到的輸出:

this == document: false
this == doc:      true
_doc == document: true
_doc == doc:      false

name: foobar
window.vanishing_global: 1366037771608
typeof window.vanishing_global: number
document.foobar: barfoo:0.9013048021588475

name: 
window.vanishing_global: undefined
typeof window.vanishing_global: undefined
document.foobar: foobar:0.5015988759696484

處理程序內的this對象應該是文檔對象。 一個文檔對象,但與它在其中運行的文檔不是同一個文檔對象(它也與父文檔不同)。 處理程序內的窗口對象也與在頁面中加載的JavaScript中運行的窗口對象不同。

最后我的問題是:

有誰知道發生了什么,以及如何獲得對實際窗口對象的引用,或者至少從同一個全局上下文聲明和引用全局變量?

腳注:

此iframe沒有跨域問題,因為它們位於同一個域中。 如果有人設置了document.domain ,則會出現問題,但在此示例代碼中沒有這樣做。

您在父頁面中聲明了所有內容。 所以對windowdocument的引用是對父頁面的引用。 如果您想對iframe執行操作,請使用iframe || iframe.contentWindow iframe || iframe.contentWindow訪問其window ,以及iframe.contentDocument || iframe.contentWindow.document iframe.contentDocument || iframe.contentWindow.document訪問其document

對於正在發生的事情有一個詞,可能是“詞匯范圍”: 什么是詞匯范圍?

范圍的唯一背景是這個。 在您的示例中,方法的所有者是doc ,這是iframedocument 除此之外,在此函數中使用已知對象訪問的任何內容都是父對象(如果未在函數中聲明)。 如果函數在不同的地方聲明,那么它將是一個不同的故事,但它在父頁面中聲明。

這是我寫它的方式:

(function () {
  var dom, win, doc, where, iframe;

  iframe = document.createElement('iframe');
  iframe.src = "javascript:false";

  where = document.getElementsByTagName('script')[0];
  where.parentNode.insertBefore(iframe, where);

  win = iframe.contentWindow || iframe;
  doc = iframe.contentDocument || iframe.contentWindow.document;

  doc.open();
  doc._l = (function (w, d) {
    return function () {
      w.vanishing_global = new Date().getTime();

      var js = d.createElement("script");
      js.src = 'test-vanishing-global.js?' + w.vanishing_global;

      w.name = "foobar";
      d.foobar = "foobar:" + Math.random();
      d.foobar = "barfoo:" + Math.random();
      d.body.appendChild(js);
    };
  })(win, doc);
  doc.write('<body onload="document._l();"></body>');
  doc.close();
})();

windoc作為wd的別名不是必需的,它可能會因為對范圍的誤解而減少混亂。 這樣,它們就是參數,您必須引用它們才能訪問iframe的內容。 如果要訪問父級,仍然使用windowdocument

我不確定向document添加方法有什么影響(在本例中為doc ),但在win上設置_l方法可能更有意義。 這樣,事情可以在沒有前綴的情況下運行......例如<body onload="_l();"></body>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM