이벤트 리스너는 웹 개발을 할때 너무나 익숙한 메서드입니다. 하지만 3번째 인자는 많이 생소한데요. 가끔 의도적으로 사용할 때가 생기면서 한번 정리해보았습니다.
목차
1. addEventListener
2.this
3. 세번째 인자
3-1. capture 속성
3-2. once 속성
3-3. passive 속성
3-4. signal 속성과 abort
3-5. useCapture 속성
4. removeEventListener 와 메모리 문제
1.addEventListener
EventTarget 인터페이스를 구현한 대상은 addEventListener() 메서드를 가지고, 대상이 이벤트를 수신할 때마다 호출할 콜백을 등록할 수 있습니다.
2.this
addEventListener() 내부 콜백의 this 대상은 e.currentTarget 과 같습니다. (*화살표 함수 x)
my_element.addEventListener("click", function (e) {
console.log(this); // my_element
console.log(e.currentTarget === this); // `true`
});
3. 세번째 인자
addEventListener(type, listener);
addEventListener(type, listener, options);
addEventListener(type, listener, useCapture);
3-1. capture 속성
이벤트가 캡처링 단계에서 실행되는지 여부 ( default : false )
이벤트 리스너의 콜백함수는 버블링 단계에서 발생하기 때문에, 자식요소와 부모요소에 동일한 이벤트가 발생한다면, 자식요소가 먼저 실행됩니다. 이를 의도적으로 조절하기 위한 옵션으로 사용할 수 있습니다.
parent.addEventListener('click', (e) => {
console.log('parent')
},{capture:true})
3-2. once 속성
이벤트 리스너가 단 1회 실행되는지 여부 ( default : false )
removeEventListener 없이 의도적으로 한번만 실행할 이벤트를 등록할 때 사용합니다.
parent.addEventListener('click', (e) => {
console.log('parent')
},{once:true})
3-3. passive 속성
passive 속성이 활성화 되면 내부 콜백에서 절대로 preventDefault() 를 호출하지 않을 것임을 나타냅니다.
만약 속성이 활성화 되었는데, preventDefault() 를 호출하면 콘솔에 경고를 표시합니다.(표시만 함)
기본값은 false 이지만 스크롤, 터치 등 일부 이벤트들은 preventDefault() 를 호출하면, 기본 동작이 수행중인 브라우저의 메인 스레드를 블록할 가능성이 생기고, 그러므로 스크롤 성능이 크게 저하될 수 있기 때문에 일부 브라우저(chrome, Firefox) 에서는 window, Document, body의 touchstart, touchmove 이벤트에 대해서는 기본값이 true 입니다.
parent.addEventListener('mousewheel', (e) => {
e.preventDefault()
console.log(e);
}, {passive:true})
3-4. signal 속성
AbortSignal 입니다. AbortSignal 의 signal 레퍼런스를 등록하면, 해당 객체의 abort() 가 호출될 때 이벤트 리스너가 제거됩니다.
보통은 fetch() 요청을 도중에 중단하기 위한 용도로 사용하곤 합니다.
const controller = new AbortController();
const signal = controller.signal;
const parent = document.querySelector('.parent');
parent.addEventListener('click', (e) => {
console.log('parent')
},{signal})
setTimeout(()=>{
controller.abort()
},3000)
3-5. useCapture 속성
세번째 인자로 객체가 아닌 boolean 값을 넣으면 useCapture 속성으로 사용됩니다.
단, useCapture 속성이 활성화 된 경우에는 캡처링, 버블링 단계도 아닌 별도의 단계에 발동됩니다.
캡처모드의 이벤트 콜백은 어떤 이벤트 콜백보다 앞서서 발동합니다.
아래처럼 하면, 캡처링 단계보다 먼저 실행됩니다.
parent.addEventListener('click', (e) => {
console.log('pre')
},true)
parent.addEventListener('click', (e) => {
console.log('parent')
},{capture:true})
// pre
// parent
4. removeEventListener 와 메모리 문제
특정 이벤트에대한 이벤트 리스 콜백은 시스템이 제한하는 한도까지는 등록이가능합니다.
여기서 등록되는 콜백은 참조값이 다르면 별개의 메모리로 등록됩니다. 그래서 항상 정적인 참조를 유지하고 removeEventListener 를 해주며 메모리를 정리해주지 않으면 메모리 누수가 쌓이게 됩니다.
아래 2가지 누수 상황과 1가지 정적 참조를 유지하는 방법 예시
// 누수1.익명함수가 누적되는 경우
for (let i = 0; i < els.length; i++) {
els[i].addEventListener("click",function (e) {});
}
// 누수2.참조되는 함수를 등록하지만, 매번 새로 등록되는 함수인경우
for (let i = 0, j = 0; i < els.length; i++) {
function processEvent(e) {
}
els[j].addEventListener("click", processEvent, false);
}
// 정적 참조를 유지하는 방법
function processEvent(e) {
}
for (let i = 0; i < els.length; i++) {
els[i].addEventListener("click", processEvent, false);
}
'FE > browser' 카테고리의 다른 글
[Browser] Service Worker 로 push notification 구현하기 (0) | 2023.09.21 |
---|---|
[Browser] Web Worker 와 Service Worker (0) | 2023.09.20 |
[Broswer] EventTarget 과 Event, CustomEvent (0) | 2023.09.20 |
Browser 에서 얻을 수 있는 모든 길이와 좌표 그리고 스크롤 (0) | 2023.05.09 |
Web Cache(웹 캐시) (0) | 2023.01.29 |