【JavaScript】JS高速化計画 イベント編
こんにちは、しきゆらです
大層なタイトルをつけましたが、続くかどうかはわかりませんね
あと、内容がお行儀がいいかどうかも保証できませんよっと
さて、本題
JSに速度を求めている今日この頃
最近は、少しでも速くなる方法があるのならば、それを使おうと思っています
ということで、今回はJSでよく使うであろう
DOMにイベントリスナーを追加する部分を見てみます
調べてみると、イベントリスナーを追加するときには
- addEventListener
- onXXX
がよく使われていて
両者には違いがあるということはよく書かれています
でも、速度の違いは・・・?
ということで簡単なコードを使って検証して見ました
詳しくは、続きから
なんでこんなことするの?
自分で書いたJSのコードが原因でブラウザが固まることが度々起こりました
(前回の記事でも書いたとおり)
そこで、少しでも速く処理できる書き方を求めて色々やっているところです
検証する内容
イベントリスナーを追加する方法としてよく使われる以下2つ
- addEventListener
- onXXX
合わせて、buttonにリスナーを追加するときはHTMLに直接
<button>ボタンを押すと何かが起こす</button>
のように書くので
JSでDOMに属性値を付加する
- setAttribute
を加えた3種類の動作速度を比較します
検証するコード
使用するのは以下
// addEventListenerの検証 function add_event_listener(num) { var div = document.createElement("div"); var time = Date.now(); for (var i = 0; i < num; i++) { div.addEventListener("click", function() { console.log("click!!!"); }); } return Date.now() - time; } // onClickの検証 function on_click(num) { var div = document.createElement("div"); var time = Date.now(); for (var i = 0; i < num; i++) { div.onclick = function() { console.log("click!!!"); }; } return Date.now() - time; } // setAttributeの検証 function set_attribute(num) { var div = document.createElement("div"); var time = Date.now(); for (var i = 0; i < num; i++) { div.setAttribute("onclick", "console.log('click!!!')"); } return Date.now() - time; } // 何度か繰り返し、平均を求める関数 // count: 平均を求めるために繰り返す回数 // num: 上記関数を繰り返す回数 function average(count, num) { var add_sum = 0, on_sum = 0, set_sum = 0; var add, on, set; for (var i = 0; i < count; i++) { add_sum += add_event_listener(num); on_sum += on_click(num); set_sum += set_attribute(num); } console.log("average"); console.log("addEventListener", add_sum / count); console.log("onClick", on_sum / count); console.log("setAttribute", set_sum / count); }
average(10, 10000)として実行した平均は以下のとおり
単位はミリ秒です
最速のものは太字にしました
Mac編
Google Chrome (54.0.2840.71 (64-bit) Mac)
addEventListener 204.2
onClick 35.1
setAttribute 19.1
Firefox (51.0a2 (2016-10-29) (64-bit) Mac)
addEventListener 764.3
onClick 16.6
setAttribute 1.9
Vivaldi (1.3.582.3 (Developer Build) (64 ビット) Mac)
addEventListener 178.8
onClick 34.5
setAttribute 19.3
Safari (10.0.1 (12602.2.14.0.7) Mac)
addEventListener 205
onClick 2.6
setAttribute 3.6
Windows編
Google Chrome ( 54.0.2840.71 m (64-bit) Windows)
addEventListener 156.5
onClick 53.8
setAttribute 23.2
Firefox (51.0a2 (2016-10-29) (64-bit) Windows)
addEventListener 652.7
onClick 27.4
setAttribute 1.9
Firefox (52.0a1 (2016-10-29) (64-bit))
addEventListener 691.1
onClick 24.3
setAttribute 2.4
Vivaldi (1.5.648.6 (Official Build) (64 ビット) Windows)
addEventListener 252.6
onClick 53.5
setAttribute 27.6
Opera (41.0.2353.46 Stable Windows (32bit))
addEventListener 228.7
onClick 56.2
setAttribute 23.5
ついでに、IEとEdgeも期待せずに計測してみました
なんと、IEに関してはコンソールを開くとエラーで落ちるため計測不能
Edgeは「num=10000」だと応答なしになってしまうため
「num=1000」として計測しました
以下、参考程度にどうぞ
Edge (39.14955.1000.0 Windows)
addEventListener 756.3
onClick 4.8
setAttribute 14.6
結果
結果として、大半のブラウザでは
setAttribute >= onClick >>>>>> addEventListener
という感じになりました
SafariとEdgeではdiv.onclickで指定した方が若干速い結果に
AppleとMicrosoftが開発するブラウザが他のブラウザとは異なる結果になったのは面白いですね
速度的には「setAttribute」を利用する方が速いですが
読みやすさ的には「onclick」等で指定する方が良さそうな感じですかね
動的にイベントを付加する場合、速度が気になるのであれば
setAttributeかonXXXで指定するのが良さそうです
なお、調べてみるとStackOverflowではこんなものもありました
http://stackoverflow.com/questions/6348494/addeventlistener-vs-onclick
複数のイベントをひとつのDOMに指定するときはaddEventListenerが良い
一つしか指定しない場合はonXXXで指定すると良い
(onXXXだと、上書きされて最後に指定したもののみが有効になるため)
ようなことが書かれていました
おわり