본문 바로가기

자바스크립트

How to avoid repeating addEventListener?

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