document.open()でスコープチェーンが破壊される?
私はローカルPCにJavaScriptの調査や実験結果によってわかったテクニックや情報をいろいろと保存しています。忘れた頃に「なんだったっけなぁ〜」と思いながら探すためです。
今日は、なんとなくフォルダの下を眺めていたら、
「document.open();によるスコープチェーンの破壊.txt」
なるファイルがあるじゃないですか!!非常に興味をそそられ(本当は昔に自分が作ったはずなのに)中身を見てみると以下のように書いてありました。
document.open();
すると、スコープチェーンが破壊されるようだ。
例えば...
・関数Aを用意
・その中でdocument.open();
・関数Bを用意
・その中でsetTimeout(自分の参照);
・関数Cを用意
・その中で、AとBを呼ぶ。
→結果
・Aで破壊されるが、Cの中ではBの参照はまだ持っている。
・Bも1回目は呼ばれる。
・だが、タイマーで自分を呼ぼうとしたとき、解決できない。
※document.open();がなければ、この現象は発生しない。
これを読んでもまだ思い出せませんでした。
そこで、れっつ実験!
<html>
<head>
<script type="text/javascript"><!--
// 関数A
function funcA() {
alert("Start funcA!");
document.open();
alert("Exit funcA.");
}
// 関数B
function funcB() {
alert("Start funcB!");
setTimeout(funcB, 0);
alert("Exit funcB.");
}
// 関数C
function funcC() {
alert("Start funcC!");
funcA();
funcB();
alert("Exit funcC.");
}
//funcC();
//--></script>
</head>
<body>
<div style="cursor:pointer;" onclick="funcC();">START</div>
<div style="cursor:pointer;" onclick="funcB();">FUNC_B</div>
</body>
</html>
⇒感想(その1)「あたりまえじゃん」
document.open();すると、今までの内容を破棄して新しく何かしようとするわけですよね。
⇒感想(その2)「ちょっとおもしろいけど、あんまり使わないなぁ」
scriptの閉じタグ直前の//funcC();をコメント外し、funcBの中のタイマーの時間を数秒くらいにして実行してみました。つまり、ファイルを読み込み途中でdocument.open();しても平気なんですね。
それに、よくよく考えると、(元のSTARTボタンで実行する場合に)document.open();したあとのソースも実行していますね。もしこれがlocation.replace("about:blank");などで画面遷移させたら、その直後からソースは実行されない*1はずです。
ふぅ〜む・・・と思ったところらへんで「そういえば半年か1年くらいまえに調査したかなぁ」とうっすら思い出しました。
【注意】なお、この件に関しては、本当にスコープチェーンが破壊されたからfuncBが実行できなくなったのかどうかという原因については、私の完全なる憶測です。ご注意ください。