3개의 버튼이 존재하고 버튼을 클릭했을 때 각 버튼은 내용이 다른 모달이 열릴 수 있도록 코드를 작성하려고했다.
그런데 addEventListener가 한번 정의되지 않고 여러 번 정의가 되서 버튼을 클릭했을 때 여러번 작동되는 문제가 발생했다. 문제를 분석해 보니 이벤트 리스너는 이벤트에 대해 등록될 때마다 새로운 객체로 생성됐다.
즉, n번 등록된 리스너의 래퍼런스는 모두 다 달라 중복 처리가 안되고 있었다.
시도1
addEventListener 중복을 피하는 핵심은 추가하기 전에 removeEventListener에 의해 추가된 처리 기능을 제거하는 것이다.
const $btn = document.getElementById('btn');
function clickHandler() {
console.info(`this is in clickHandler`);
}
$btn.removeEventListener('click', clickHandler);
$btn.addEventListener('click', clickHandler);
그러나 여기에 문제가 발생할 수 있다. 자바스크립트에서 함수는 reference type 이다. 그러므로 removeEventListener가 실행 될 때, 두번째 파라미터는 addEventListener의 참조와 동일해야 하며 그렇지 않으면 제거 효과를 얻을 수 없다.
시도2
const $btn = document.getElementById('btn');
let count = 0;
function addListener() {
if ($btn.clickHandler) {
$btn.removeEventListener('click', $btn.clickHandler);
}
$btn.clickHandler = () => {
console.info(`this is in clickHandler but created ${++count} times`);
};
$btn.addEventListener('click', $btn.clickHandler);
}
$btn을 clickHandler에 unique한 참조를 할 수 있도록 했다. 이렇게하면 예상한대로 removeEventListener가 잘 작동이 된다.
'자바스크립트' 카테고리의 다른 글
Function.prototype.bind() (0) | 2021.11.10 |
---|---|
Jquery UI draggable creates a whitespace (0) | 2021.11.05 |
modal popup 구현 (0) | 2021.09.06 |
script 태그의 async와 defer 속성 (0) | 2021.08.26 |
Javascript’s __proto__ vs prototype (0) | 2021.06.28 |