コードを貼り付ける前に、シナリオを次に示します。
- JavaScript を使用して空の iframe を作成する HTML ドキュメントがあります。
- JavaScript は関数を作成し、その関数への参照を iframe のドキュメント オブジェクトにアタッチします (ドキュメント
doc.open()
への参照を取得するために使用します)。 - 関数は
onload
、iframe のドキュメントのハンドラーとしてアタッチされます (<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);
指示:
これら 2 つのファイルをディレクトリに配置し、ブラウザーで 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
が、このサンプル コードではそれが行われていません。