- ベストアンサー
重い処理とはどのようなものがあるか
javascriptを結構作ったページを作った結果、結構な頻度で操作をするページの割りに1操作につき0.2秒くらいの重さを感じるようになってしまいました C2D E8600な開発環境でこのくらい重いのだともっとCPUの弱いPCだともっと遅くなるだろうとおもうので出来るだけ早くしたいのです 「こういう命令を多様すると重くなるよ」というのを教えてもらえませんか? もしくは書いてあるサイトなどは無いでしょうか また逆に多用してもさほど重くならない命令もありましたらお願いします 感覚的には変数/配列に代入/参照はかなり多用しても軽い感じがしました いろいろ試した結果 ・getElementById('hoge').selectedIndexを減らしてみた 536回程度繰り返してるforの外で先に変数に取得した値を入れて計算させたところ、1/5の時間程度になりました 130件くらいのHTMLへ表示させるために使っていた方法を ・document.all.NAMEをdocument.getElementByIdに変えてみた ・document.getElementById('hoge').InnerHTML/InnerTextで表示させていた部分をdocument.FORM.ELEMENT(テキスト入力欄).valueに入れて擬似表示させているところがあったのでまねてやって見た ↑2個は一緒にやったのでどちらが効果あったのかはわかりませんが これも1/5くらいになりました ・300x2程度の配列にいれてある値を for (i = 0; i < array.length; i++) { document.FORM.SELECTOPTION.options[i] = new Option(array[i][1],array[i][0]); ~×16回 } 代替方法を思いついたのと重すぎたので使ってません document.getElementByIdを多用すると重くなる? new Optionはそもそも重い? これの理由なども教えていただけると助かります また、 function ID(id){ return document.getElementById(id); } のように書いてあるところも見かけました、処理的には自分のところと大して変わらない(むしろ多いくらい)の量だったのですが、軽かったです 書きやすくするための方法かとおもったんですが早くなる効果もあるんでしょうか? その他、 ・文字列連結は重い ・document.writeは重い などを聞いたことがあります
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
> ・document.all.NAMEをdocument.getElementByIdに変えてみた これ自体に効果はありません。 allはプロパティ、getElementById()がメソッドですので、メソッドの方が遅くなる可能性はあります。 > ・getElementById('hoge').selectedIndexを減らしてみた for(var i=0,i<100;i++){ document.getElementById('elm'+i).style.color='white'; document.getElementById('elm'+i).style.fontSize='large'; } などとしていたら、 for(var i=0,i<100;i++){ var st=document.getElementById('elm'+i).style; st.color='white'; st.fontSize='large'; } のように、"."での連結(プロパティの走査)を少しでも減らすと早くなります。 document.allはFirefox2以前やSafari3.1以前、Opera9.2以前などのJScriptをサポートしないブラウザで動かないので、 JScript未対応ブラウザも考慮するなら、DOMでないとダメです。 document.allがあまり使われないのは、利用できる環境(ブラウザ)が少ないためです。 > ・document.getElementById('hoge').InnerHTML/InnerTextで表示させていた部分をdocument.FORM.ELEMENT(テキスト入力欄).valueに入れて擬似表示させているところがあったのでまねてやって見た 速度的には (遅い) innerHTML < innerText < value (早い) ですが、フォームフィールドになる、HTMLタグを使えないなどの条件が出てきます。 .innerTextはJScriptですので、JScript未対応ブラウザでは.textContentを使わなければダメです。 > document.FORM.SELECTOPTION.options[i] = new Option(array[i][1],array[i][0]); document.createElement('option')を使う方法もありますが、ほとんど変わらないと思います。 要素生成は1つずつ作っていくよりも、.innerHTMLの方が早いです。 が、<select>でこれをやるのはどうにも、、、 for (i = 0; i < array.length; i++) { s+='<option value="'+array[i][1]+'">'+array[i][0]+'</option>'; } document.FORM.SELECTOPTION.innerHTML=s; <select>の場合は、あらかじめlengthを指定しておくのが一番早いと思います。 for(var i=0, sel=document.FORM.SELECTOPTION, sel.options=300 ; i<300 ; i++){ sel.options[i].text=array[i][0]; sel.options[i].value=array[i][1]; } 別の方法、 o=sel.options[i]; o.text=array[i][0]; o.value=array[i][1]; としても良いのですが、2行だけなら大して変わらないと思います。 > ・文字列連結は重い 処理が重くなる条件があります。 var ary=['hello', ' ', 'world']; var s=''; for(var i=0; i<ary.length;i++){ s+=ary[i]; } 配列を1つずつ連結するよりも、 s=ary.join(''); の方が早いです。 s=''; s+='hello'; s+=' '; s+='world'; 1語ずつ分けるよりも s='hello'+' '+'world'; 1行で書いた方が早いです。 > ・document.writeは重い <script> document.write('<div>hello</div>'); </script> よりも <div>hello</div> スクリプトを使わないHTMLべた書きの方が早いです。 document.all.innerHTML='<div>hello</div>'; と比べれば、document.write()の方が早いです。 (document.write()は1回だけ画面描画をするのに対し、.innerHTMLは画面を描画した後に使用し、.innerHTMLを書き換えた後でもう一度描画し直すから) > function ID(id){ > return document.getElementById(id); > } "document.getElementById"は23文字書かなければなりませんが、"ID"は2文字で済むと言うだけです。 ID()という関数が介入する分、処理は遅くなります。 変数名、関数名の字数は短いほど早くなります。 (Perl、PHPなど、インタプリタ型言語で共通です。C系、Javaなどのコンパイル型言語は変数名の字数は影響しません。) var n; for(var i=0;i<1000;i++) n=0; var abcdefgabcdefgabcdefg ... 100字ほど続く; for(var zzz(100字ほど続く変数名)=0;zzz<1000;zzz++) abcde.... =0; DOMなどの最新のスクリプトは遅いのが多いので、 古いサイトや古い書き方などを調べたりすると、結構早くなったりします。
その他の回答 (2)
- 神崎 渉瑠(@taloo)
- ベストアンサー率44% (1016/2280)
間違えてた。m(_ _)m forループの初期化処理の部分は、 sel.options.length=300 です。 以下に訂正です。 -------- <select>の場合は、あらかじめlengthを指定しておくのが一番早いと思います。 for(var i=0, sel=document.FORM.SELECTOPTION, sel.options.length=300 ; i<300 ; i++){ sel.options[i].text=array[i][0]; sel.options[i].value=array[i][1]; } ---------
鉄則ですが、まず一番多く繰り替えしている処理 (ループ) を見付けましょう。 その中で、結果を使い回せるところは全部使いまわしましょう。 具体的には、document.all.NAME とか document.getElementById('hoge') とか、こういうのを130回もやるのは効率が悪すぎます。 親要素が共通なんだったら、そこだけに id を振って、 var parent = document.getElementById(PARENT); と取得しておいて、 var list = parent.getElementsByTagName(TAG) for(var i=0,len=list.length;i<len;i++){list[i].innerHTML=ほにゃらら} とか var child = parent.firstChild; while(child){ if(child.nodeType!=1){ child.innerHTML = ほにゃらら }; child = child.nextSibling; } とかやると効率が出るのは分かりますか? もしformの要素だったらinnerHTMLよりvalueを使ったらいいというのは、innerHTMLはDOM構造に手を出しかねないので重い処理と相場が決まっているからです。valueだったら内部の文字列を触るだけなので、内部でやっていることが全然違います。(もちろん、ループをやめて innerHTML で一回で処理してしまうならそれは速いですよ) new演算子は重いので多用するものではありません。JavaScriptは関数生成がすごく遅いです。 function ID(id) とか function $(id) とかを宣言するのは単にdocument.getElementByIdと何度も書くのが面倒だからです。速くはなりません。 参考になるかもしれないのはこことか。 http://www.hyuki.com/yukiwiki/wiki.cgi?EfficientJavaScript 1操作につき0.2秒かかっている操作のコードを貼ってみると、もっといい答えがもらえるかもしれませんよ。
お礼
>もしformの要素だったらinnerHTMLよりvalueを使ったらいいというのは、innerHTMLはDOM構造に手を出しかねないので重い処理と相場が決まっているからです。 まさに知りたかったのはこういうことです ループを見直すなど目にわかる部分はまだいじりやすいのですが 内部的に重い処理と軽い処理の違いがよくわからなかったので 参考URLがとってもためになりました
お礼
ほぼすべての項目に詳しく解説をしていただきありがとうございます DOMに手を入れない、条件判断や変数同士の操作ならそれほど遅くなることは無いみたいですね