reference
https://kostasbariotis.com/removeeventlistener-and-this/
이벤트 리스너 등록을 위해 addEventListener 메소드를 사용한다
등록된 이벤트 리스너를 제거하기 위해 removeEventListener 메소드를 사용한다
target.addEventListener(type, listener, useCapture);
target.removeEventListener(type, listener, useCapture);
호출되는 listener 함수의 this는 target이 되는 엘리먼트(.)를 가르킨다
bind, call, apply 메소드는 근본적으로 동일한 목적인
this에 대한 참조를 제어할 때 사용한다
bind() 는 this 값을 설정하고 새로운 함수를 생성한다
call(), apply() 는 함수를 생성하는 것이 아니라 호출한다
const createButton = (() => {
function addEvents() {
this.el.addEventListener("click", this.clickHandler);
}
return class Button {
constructor() {
this.el = document.createElement("button");
}
clickHandler() {
console.log("clickHandler");
}
}
})();
const newButton = new createButton();
newButton.el.dispatchEvent(new Event("click"))
클릭 이벤트에 대한 핸들러 함수를 등록하기 위한 addEvnets 함수는 Button 클래스가 아닌 다른 context에 동작한다
const createButton = (() => {
function addEvents() {
this.el.addEventListener("click", this.clickHandler);
}
return class Button {
constructor() {
this.el = document.createElement("button");
addEvents();
}
clickHandler() {
console.log("clickHandler");
}
}
})();
const newButton = new createButton();
newButton.el.dispatchEvent(new Event("click"))
addEvents 함수는 현재 window를 참조하고 있기 때문에 동작하지 않는다
addEvents 함수에서의 this.el은 button이 되어야 한다
call 메서드를 사용해서 this 값을 전달해야 한다
const createButton = (() => {
function addEvents() {
this.el.addEventListener("click", this.clickHandler);
}
return class Button {
constructor() {
this.el = document.createElement("button");
addEvents.call(this);
}
clickHandler() {
console.log("clickHandler");
}
}
})();
const newButton = new createButton();
newButton.el.dispatchEvent(new Event("click"))
정상적으로 동작한다
clickHanlder에서 arr에 1을 추가하는 로직을 추가하도 실행하면
const createButton = (() => {
function addEvents() {
console.log(this); // Button {el: button, arr: Array(0)}
this.el.addEventListener('click', this.clickHandler);
}
return class Button {
constructor() {
this.el = document.createElement('button');
this.arr = [];
addEvents.call(this);
}
clickHandler() {
console.log(this); // button
this.arr.push(1);
}
};
})();
const newButton = new createButton();
newButton.el.dispatchEvent(new Event('click'));
clickHandler 메서드 내의 this는 button element이다
addEvents 함수에 call을 통해 원하는 this를 전달한 것처럼
clickHandler 함수 또한 this를 전달해주면 된다
bind를 통해 this를 전달 및 새로운 함수르 생성함으로 콜백 형식을 유지할 수 있다
const createButton = (() => {
function addEvents() {
console.log(this); // Button {el: button, arr: Array(0)}
this.el.addEventListener('click', this.clickHandler.bind(this));
}
return class Button {
constructor() {
this.el = document.createElement('button');
this.arr = [];
addEvents.call(this);
}
clickHandler() {
console.log(this); // Button {el: button, arr: Array(0)}
this.arr.push(1);
console.log(this.arr); // [1]
}
};
})();
const newButton = new createButton();
newButton.el.dispatchEvent(new Event('click'));
removeEventListener 를 사용해 이벤트 리스너를 작성해보자
const createButton = (() => {
function addEvents() {
console.log(this); // Button {el: button, arr: Array(0)}
this.el.addEventListener('click', this.clickHandler.bind(this));
}
function removeEvents() {
console.log(this)
this.el.removeEventListener('click', this.clickHandler.bind(this));
}
return class Button {
constructor() {
this.el = document.createElement('button');
this.arr = [];
addEvents.call(this);
}
clickHandler() {
console.log(this); // Button {el: button, arr: Array(0)}
this.arr.push(1);
console.log(this.arr); // [1]
}
removeHandler() {
removeEvents.call(this);
}
};
})();
const newButton = new createButton();
newButton.el.dispatchEvent(new Event('click')); // [1]
newButton.removeHanlder();
newButton.el.dispatchEvent(new Event('click')); // [1, 1]
bind 를 통해 리스너 함수를 지정했다
bind 는 새로운 함수를 생성하기 때문에 addEventListener와 removeEventListener의 리스너 함수는 같지 않다
bind 한 함수를 리스너에서 할당하는 것이 아니라 미리 할당해놓으면 가능하다
click event가 발생하더라도 clickHandler 메서드가 호출되지 않는다
const createButton = (() => {
function addEvents() {
console.log(this); // Button {el: button, arr: Array(0)}
this.el.addEventListener('click', this.clickHandler);
}
function removeEvents() {
console.log(this)
this.el.removeEventListener('click', this.clickHandler);
}
return class Button {
constructor() {
this.el = document.createElement('button');
this.arr = [];
this.clickHandler = this.clickHandler.bind(this);
addEvents.call(this);
}
clickHandler() {
console.log(this); // Button {el: button, arr: Array(0)}
this.arr.push(1);
console.log(this.arr); // [1]
}
removeHandler() {
removeEvents.call(this);
}
};
})();
const newButton = new createButton();
newButton.el.dispatchEvent(new Event('click')); // [1]
newButton.removeHanlder();
newButton.el.dispatchEvent(new Event('click')); // [1]