EfficientJavaScript によると
http://www.hyuki.com/yukiwiki/wiki.cgi?EfficientJavaScript
evalは重いので非推奨らしい。
さて、ではどうするか
JavaScriptタグを動的に書き出す方針でやってみた。
動かない例1 InnerHTMLで追加してみる(InnerText)も同じ
script = document.createElement("script"); script.type="text/javascript"; script.innerHTML = "alert('')";
動かない例2 Textノードで追加してみる
script = document.createElement("script"); script.type="text/javascript"; script.appendChild(document.createTextNode("alert()"));
ScriptタグにInnerHTMLを書き出すのは無理だった。
つまり、DOMで参照してるから無理って事のようだ。DOMでアクセスしているからどちらの例も同じ結果でも納得できる。
Scriptタグ内にソースを書出す方法
動きそうな例 をみつけた
http://d.hatena.ne.jp/brazil/20061105/1162722198
のコメントによると
script = document.createElement("script"); script.type="text/javascript"; script.text = "alert()";
だと動くらしい。ただ、これは未検証。
textプロパティの参照は微妙かも
さがしてみした結果 (IE6で検証)
http://d.hatena.ne.jp/shogo4405/20061107/1162886968
によると
script = document.createElement("script"); script.type="text/javascript"; script.text = "alert()";
textプロパティーは動作するらしい。でもバッドノウハウ?
defer属性が正攻法のようです。
id:shogo4405さんの別のエントリ
http://d.hatena.ne.jp/shogo4405/20070306/1173160753
deferなるAttributeが存在するらしい。試してみた
div = document.createElement("div"); div.innerHTML = " <script defer='defer'>alert('');</script>"; document.body.appendChild(div);
おおお動いた。
defer属性すごいよ。script src="xxx.js"だとタイミング制御が難しいが。
これならタイミングを制御できる。(*)動作検証したソース無くしたので、サンプルソースは適当。Scriptタグの直前にTextノードを書き出すのがミソ
しかしドコで使うか微妙。
2012-01-05 追記 async と defer
defer はDomContentLoadedのイベントで実行される。
async は onload の直前で実行される。
【レポート】script要素、asyncとdeferの効果 | 開発・SE | マイナビニュース
asyncはedvakfさんに教えてもらった。
WSHからIEを操作するときに使える
WSH(js)でYahooをスクレーピングするときに、CSSセレクタが使えると便利。
/** * WSHでIEを制御して必要なデータを取り出す */ var url = "http://www.yahoo.co.jp"; var ie = WScript.CreateObject("InternetExplorer.Application"); ie.Navigate2( url ); ie.visible = true; while( ie.ReadyState != 4 ){ WScript.Sleep(1); } var document = ie.Document; //Prototype.jsなどライブラリを読み込む //JScriptとIEのJavaScriptを連携させる var fs = WScript.CreateObject("Scripting.FileSystemObject"); fs.OpenTextFile( "ext.js" );//Extライブラリを読み込んでみる ext_src = fs.ReadAll(); div = document.createElement("div"); div.innerHTML = " <script defer='defer'>"+ext_src+"</script>"; document.body.appendChild(div); div = document.createElement("div"); div.innerHTML = " <script defer='defer'>" +"var obj = Ext.query('#element div');" +"</script>"; document.body.appendChild(div); //取り出した結果をJSDBでデータベースへ //JSDBの使い方をまだ調べてない
こんな感じ?でも動作しない。ext.jsが大きすぎる?
XPATHつかえるからCSS Selectorライブラリって余り使わないよね。。。
やっぱりdeferの使いどころが難しい。
参考
http://youmos.com/news/css_selector_js
うまくいけば、Youtube動画を保存しながらMHTMLを作れるかなと思ったのだが。
ところでevalより軽いの?
作業が脱線したので動作速度は検証できてない 笑
どうなんだろう
まとめ
副産物が生まれた。WSHからIEのDocumentオブジェクトをどうさせる方法
EmEditorのマクロでHTMLプレビューしながら動的に連携出来るよね。
(EmEditorのマクロがイベントドリブンすれば・・・)きっと萌ディタなら出来るぞ。
最速のma.laさんがやってた、動的ロードDEMOがローカルだけで出来るんじゃないかなと妄想してみた。
/** * WSHでIE書き換えてAlertを出す。 */ var url = "http://www.yahoo.co.jp"; var ie = WScript.CreateObject("InternetExplorer.Application"); ie.Navigate2( url ); ie.visible = true; while( ie.ReadyState != 4 ){ WScript.Sleep(1); } var document = ie.Document; var window = document.parentWindow; with(window){ //このスコープがIEとほぼ同じスコープになる alert("Hello form IE window"); }
コレをベースに
- IEのWindowを再利用するClass作って
- HTMLソースを書き換えるClass作る
- エディタのイベントでbodyを書き換える
でも、contentEditableを応用した方が楽だろう・・・
もしかして
FireBugのようなconsleもeval使わずに作れるかも。