理解度テスト: addEventListener()
に渡される 3 番目のパラメータの目的は何ですか?
addEventListener()
が 2 つのパラメータしか受け取らないと思っていたり、泡に関係があるという漠然とした理解で false
の値を常にハードコードしていたりしても、恥ずかしがる必要はありません。
より柔軟に設定できる addEventListener()
addEventListener()
メソッドは、ウェブの初期から長い道のりを歩んできました。その新しい機能は、3 番目のパラメータのスーパーチャージ版を介して構成されます。メソッドの定義の最近の変更により、デベロッパーは 構成オブジェクトを介して追加のオプションを提供できるようになりました。また、ブール値パラメータがある場合やオプションが指定されていない場合でも、下位互換性を維持できます。
Chrome 55 では、その設定オブジェクトの once
オプションが、passive
オプション(Chrome 51 で実装)と capture
オプション(Chrome 49 で実装)とともにサポートされるようになりました。次に例を示します。
element.addEventListener('click', myClickHandler, {
once: true,
passive: true,
capture: true
});
これらのオプションは、ユースケースに応じて組み合わせることができます。
後片付けのメリット
これが新しい once
オプションを使用する構文ですが、これによって何が得られるのでしょうか。つまり、1 回限りのユースケースに適したイベント リスナーが提供されます。
デフォルトでは、イベント リスナーは最初の呼び出し後に保持されます。これは、複数回クリックできるボタンなど、一部のイベントタイプで望ましい動作です。ただし、他の用途では、イベント リスナーを保持する必要はありません。1 回だけ実行する必要があるコールバックがある場合、望ましくない動作につながる可能性があります。衛生的なデベロッパーは、常に removeEventListener()
を使用して、次のようなパターンに沿って明示的にクリーンアップするオプションがありました。
element.addEventListener('click', function cb(event) {
// ...one-time handling of the click event...
event.currentTarget.removeEventListener(event.type, cb);
});
新しい once
パラメータを使用する同等のコードを記述すると、コードが簡潔になり、イベント名(上の例では event.type
)やコールバック関数への参照(cb
)を追跡する必要がなくなります。
element.addEventListener('click', function(event) {
// ...one-time handling of the click event...
}, {once: true});
イベント ハンドラをクリーンアップすると、コールバック関数に関連付けられたスコープを破棄し、そのスコープでキャプチャされた変数をガベージ コレクションできるため、メモリ効率も向上します。次に、違いを生む例を示します。
function setUpListeners() {
var data = ['one', 'two', '...etc.'];
window.addEventListener('load', function() {
doSomethingWithSomeData(data);
// data is now part of the callback's scope.
});
}
デフォルトでは、load
イベント リスナー コールバックは、実行が完了しても、再び使用されなくてもスコープ内に残ります。data
変数はコールバック内で使用されるため、スコープ内に残り、ガベージ コレクションは行われません。ただし、once
パラメータでコールバックが削除された場合、関数自体とそのスコープで保持されているすべてのものがガベージ コレクションの候補になる可能性があります。
ブラウザ サポート
Chrome 55 以降、Firefox 50 以降、Safari の技術プレビュー 7 以降では、once
オプションがネイティブでサポートされています。
多くの JavaScript UI ライブラリには、イベント リスナーを作成する便利なメソッドが用意されています。また、ワンタイム イベントを定義するためのショートカットも用意されています。最も有名なものは jQuery の one()
メソッドです。ポストポリフィルも、Andrea Giammarchi の dom4
ライブラリの一部として利用できます。
ありがとう
この投稿のサンプルコードに関するフィードバックを送信していただいた Ingvar Stepanyan 様、ありがとうございます。