JavaScript TUEEEEEEEってなるdocument.writeのテクニック

外部からscriptタグで読み込んだJSファイル内でdocument.writeが使われていると、ページ全体が書き換えられてしまう。ページのDOM構築終了後にdocument.writeしちゃったりすると、こういうことが起こる。
基本的に外部のコードとかはDOM構築の段階で読み込むので問題は起こらないんだけど、例えばscriptタグをDOM構築終了後、あとからDOMに追加して遅延ロードさせたコード内でdocument.writeが使われていると、ページが書き換わってしまう。
もちろんそれだと困る。だけど外部のコードだと書き換えることもできない。
最近そういうケースがあって困っていたらこんな記事を見つけた。
document.write()の実行タイミングをずらす方法
外部のコードでdocument.writeを使われるとタイミング的にまずい事がある…だったら都合がいいようにdocument.writeを別で置き換えちゃえば?ってこと。これはちょっと考えれば思いつく事なのかもしれないけど、目からウロコ、「ハッ!」ってなった。

(function(){
  var alts = []; // document.writeの内容を入れておく配列を準備 
  d._write = d.write; // オリジナルはコピーしておく
  d.write = function(s){ alts.push(s);} // d.writeを新たに定義
 }());

この部分。(ここではいきなり d が使われてるけど、まぁ document を指してる変数。)
document.writeをdocument._writeに退避させ、document.writeには受け取った引数を配列altsへ格納する関数を代入している。これにより通常document.write("hoge")とかでページに「hoge」が書き出されてしまうのを防いでる。でも書きだそうとした内容はしっかりセーブされてる。
これで安心して外部コードを読み込めるってんで

  var src = "http://www.blogpeople.net/display/usr/0f0d40535b5b4103.js";
  var script = d.createElement('script');
  script.setAttribute('type', 'text/javascript');
  script.setAttribute('charset', 'euc-jp');
  script.setAttribute('src', src);
  d.getElementsByTagName('head')[0].appendChild(script);

DOMにscriptタグを追加して外部コードを読み込み実行させる。 d.getElementsByTagName('head')[0].appendChild(script);をしてコードが実行された時点で書き換えられたdocument.writeが走り、配列altsへ本来書き出したい内容が保存されていく。
そしてコードが実行を終えると(ロードが終わった)、windowのloadイベントが走る。

  addEvent(window, "load", function(){
   o("_webRing").innerHTML = alts.join(""); // 指定した場所に流し込む
   d.write = d._write; // d.writeを元の定義に戻しておく
  });

配列altsに保存された内容を実際に書き出したかった場所に自分で流し込むことで、安全に外部コード実行により得られるコンテンツを取得できる。そして得るもん得たらdocument.writeを元に戻す。これで完了。

正にJavaScriptっていうコードだよね。この記事見たとき改めてJavaScriptおもすれえええwwwって思った。2006年とだいぶ古い記事にはなるのだけど、いい情報発掘できました。現在でも使える便利テクニック。


っていうかそもそも外部コードでdocument.write使うのってどうなの。