Detektor zdarzeń

Szybki quiz: do czego służy trzeci parametr przekazywany do funkcji addEventListener()?

Nie wstydź się, jeśli uważasz, że funkcja addEventListener() przyjmuje tylko 2 parametry, lub jeśli zawsze zamiast niej używasz zaimplementowanej na stałe wartości false, mając mgliste pojęcie, że ma ona coś wspólnego z bąbelkami.

bardziej konfigurowalna funkcja addEventListener();

Od początków internetu metoda addEventListener() przeszła długą drogę, a jej nowa funkcjonalność jest konfigurowana za pomocą wzmocnionej wersji tego trzeciego parametru. Najnowsze zmiany w definicji metody pozwalają deweloperom udostępniać dodatkowe opcje za pomocą obiektu konfiguracji, zachowując przy tym zgodność wsteczną, gdy występuje parametr logiczny lub gdy nie jest określona opcja.

Z przyjemnością informujemy, że Chrome 55 obsługuje opcję once w tym obiekcie konfiguracji, obok opcji passive (wdrożonej w Chrome 51) i capture (wdrożonej w Chrome 49). Na przykład:

element.addEventListener('click', myClickHandler, {
    once: true,
    passive: true,
    capture: true
});

Możesz dowolnie łączyć i dopasowywać te opcje w sposób odpowiedni do Twojego przypadku użycia.

Korzyści z sprzątania po sobie

Oto składnia używania nowej opcji once. Jakie korzyści Ci to przyniesie? Krótko mówiąc, jest to detekcja zdarzeń dostosowana do przypadków użycia typu „jeden i wystarczy”.

Domyślnie detektory zdarzeń są zachowywane po pierwszym wywołaniu, co jest przydatne w przypadku niektórych typów zdarzeń, np. przycisków, które można klikać wielokrotnie. W innych przypadkach nie jest konieczne utrzymywanie detektorów zdarzeń, a ich użycie może prowadzić do niepożądanego zachowania, jeśli masz funkcję wywołania zwrotnego, która musi być wykonywana tylko raz. Deweloperzy dbający o czystość kodu zawsze mieli możliwość korzystania z funkcji removeEventListener(), aby wyraźnie porządkować kod, stosując wzorce takie jak:

element.addEventListener('click', function cb(event) {
    // ...one-time handling of the click event...
    event.currentTarget.removeEventListener(event.type, cb);
});

Odpowiednio kod, który korzysta z nowego parametru once, jest czystszy i nie wymaga śledzenia nazwy zdarzenia (event.type w poprzednim przykładzie) ani odwołania do funkcji wywołania zwrotnego (cb):

element.addEventListener('click', function(event) {
    // ...one-time handling of the click event...
}, {once: true});

Oczyszczanie metod obsługi zdarzeń może też zwiększyć wydajność pamięci przez zniszczenie zakresu powiązanego z funkcją wywołania zwrotnego, co pozwala na zebranie wszystkich zmiennych uchwyconych w tym zakresie. Oto przykład, w którym może to mieć znaczenie:

function setUpListeners() {
    var data = ['one', 'two', '...etc.'];

    window.addEventListener('load', function() {
    doSomethingWithSomeData(data);
    // data is now part of the callback's scope.
    });
}

Domyślnie wywołanie zwrotne detektora zdarzeń load pozostanie w zakresie po zakończeniu działania, nawet jeśli nigdy więcej nie zostanie użyte. Ponieważ zmienna data jest używana w obiekcie wywołania zwrotnego, pozostanie w zakresie i nigdy nie zostanie zebrana przez garbage collector. Jeśli jednak wywołanie zwrotne zostanie usunięte za pomocą parametru once, zarówno sama funkcja, jak i wszystko, co jest utrzymywane w ramach jej zakresu, może zostać uznane za kandydata do usunięcia przez mechanizm garbage collection.

Obsługa przeglądarek

Chrome 55+, Firefox 50+ i Safari Technology Preview 7+ mają wbudowane obsługę opcji once.

Wiele bibliotek interfejsu użytkownika JavaScript udostępnia wygodne metody tworzenia odbiorców zdarzeń, a niektóre z nich mają skróty do definiowania zdarzeń jednorazowych. Najbardziej znana jest metoda one() jQuery. W ramach dom4biblioteki Andrea Giammarchi jest też dostępny polyfill.

Dziękujemy

Dziękujemy Ingvarowi Stepanyanowi za opinię na temat przykładowego kodu w tym poście.