イベントバブリング
理論上はイベントバブリングによってルートノード(document
)に辿り着くまでに伝播する数だけパフォーマンスに差が出ます。
HTML
1<!DOCTYPE html>
2<html>
3 <head>
4 <title>sample</title>
5 <script src="./jquery-3.1.1.js"></script>
6 <script>
7 'use strict';
8 jQuery(document).on('click', '.bar', function (event) {
9 console.log(event.type);
10 });
11 </script>
12 </head>
13 <body>
14 <main>
15 <ul id="foo">
16 <li class="bar">bar</li>
17 <li class="bar">bar</li>
18 <li class="bar">bar</li>
19 <li class="bar">bar</li>
20 </ul>
21 </main>
22 </body>
23</html>
上記HTMLでは「li -> ul -> main -> body -> html -> document」と伝播されます。
伝播する数を抑える為にはより対象の要素ノードに近い場所にイベント定義する必要があります。
この例でいえば、#foo
でイベント定義すればいいでしょう。
JavaScript
1jQuery('#foo').on('click', '.bar', function (event) {
2 console.log(event.type);
3});
上記コードを適用するには </body>
直前にコードを書くか、jQuery(function () {})
内に定義する必要があります。
伝播する数を0にするには .bar
自身にイベント定義しなければなりません。
JavaScript
1jQuery('.bar').on('click', function (event) {
2 console.log(event.type);
3});
この場合、動的に <li class="bar">
が挿入された要素ノードまでは対応できませんので、動的に要素ノードを追加する処理の方でイベント定義する必要があります。
MutationObserver
MutationObserver
を使用すれば、動的に要素ノードが挿入されたタイミングでイベント定義する事が可能です。
ただし、要素ノードが追加される度に MutationObserver のチェック処理が走る事になり、全ての要素ノードの挿入処理のパフォーマンスが低下します。
つまり、他の機能でノード挿入処理があった場合、そちらのノード挿入処理のパフォーマンスも低下してしまいます。
他のノード挿入時のパフォーマンス低下を防ぐ為には「.bar
を挿入処理となるコード」に「clickイベント定義処理」となるコードを追加する必要があります。
メモリ
イベントを定義した数だけメモリを消費する事になります。
ルートノード(document
)にイベント定義すればメモリ消費量はわずかですが、各要素ノード(.bar
)にイベント定義すれば、.bar
の存在する数だけ比例してメモリ消費量は増えます。
従って、対象の要素数が膨大になる場合はメモリを圧迫してパフォーマンスに影響が出る可能性があります。
jQuery
当然ですが、jQueryの独自処理分もコストがかかります。
素のJavaScriptで書けば、より高いパフォーマンスが得られます。
JavaScript
1document.getElementById('foo').addEventListener('click', function (event) {
2 var li = event.target;
3
4 if (li.classList.contains('bar')) {
5 console.log(event.type);
6 }
7}, false);
パフォーマンス検証
最終的にはバランスです。
適用されるHTML/CSSによってもパフォーマンスが変わってくるので、実際にコードを書いて動かしてパフォーマンスを比較してみるのが一番だと思います。
Re: hoshiimohunda さん