깜짝 퀴즈: addEventListener()
에 전달된 세 번째 매개변수의 용도는 무엇인가요?
addEventListener()
가 두 개의 매개변수만 사용한다고 생각했거나, 아니면 거품과 관련이 있다는 모호한 이해를 바탕으로 항상 false
값을 하드코딩했다면 당황하지 마세요.
더 구성 가능한 addEventListener()
addEventListener()
메서드는 웹 초창기부터 많은 발전을 거쳤으며, 새로운 기능은 세 번째 매개변수의 슈퍼차지 버전을 통해 구성됩니다. 최근 메서드 정의가 변경되어 개발자는 구성 객체를 통해 추가 옵션을 제공할 수 있으며, 부울 매개변수가 있거나 옵션이 지정되지 않은 경우 이전 버전과 호환됩니다.
Chrome 55에서는 passive
(Chrome 51에서 구현) 및 capture
옵션 (Chrome 49에서 구현)과 함께 구성 객체에 once
옵션에 대한 지원을 추가합니다. 예를 들면 다음과 같습니다.
element.addEventListener('click', myClickHandler, {
once: true,
passive: true,
capture: true
});
이러한 옵션은 사용 사례에 따라 조합할 수 있습니다.
직접 정리하는 이점
새 once
옵션을 사용하는 구문은 다음과 같습니다. 그러면 어떤 이점이 있나요? 즉, '완료 후 닫기' 사용 사례에 맞게 조정된 이벤트 리스너를 제공합니다.
기본적으로 이벤트 리스너는 처음 호출된 후에도 유지됩니다. 이는 여러 번 클릭할 수 있는 버튼과 같은 일부 유형의 이벤트에 적합합니다. 하지만 다른 용도의 경우 이벤트 리스너가 계속 유지될 필요가 없으며, 한 번만 실행해야 하는 콜백이 있는 경우 원치 않는 동작이 발생할 수 있습니다. 항상 위생적인 개발자는 다음과 같은 패턴에 따라 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님께 감사드립니다.