이 글은 이 포스트의 연장선에 있습니다.
같은 동작을 가진 함수를 바인딩하더라도, 경우에 따라서 실제로는 다른 값을 가지는 경우가 있습니다.
함수의 선언 방식에 따라 이벤트를 어떻게 바인딩하는 것이 좋을지에 대해 알아보겠습니다.
this
이벤트에 함수를 바인딩 할 때, this
는 특히 신경써야 하는 부분입니다.
this
에 대한 정보는 아래 그림처럼 실행 콘텍스트 객체에 포함되어 있습니다.
그러나 호출에 따라 다른 값이 할당되기 때문에 함수 내부 구조만 보고서는 this 값을 정확히 예측하기란 어렵습니다.
때문에 this가 어느 곳을 바라보고 있는지 알아내려면 아래 내용들을 살펴보아야 합니다.
함수의 종류에 따라
일반적인 함수와 화살표 함수가 가리키는 this
는 서로 다릅니다.
const obj = {
foo: function () {
console.log(this);
},
bar: () => {
console.log(this);
},
}
obj.foo();
obj.bar();
obj.foo()
의 경우 this
가 obj
를 가리키고 있지만, obj.bar()
은 전역 객체인 window
를 가리키게 됩니다.
이는 일반 함수가 바라보는 this
의 경우 함수가 종속되어 있는 객체를 가리키기 때문이고, 화살표 함수가 바라보는 this
는 해당 함수가 종속되어 있는 인스턴스를 갖기 때문입니다.
두 방식은 분명히 다르지만, 아래 코드처럼 상위에 같은 인스턴스를 갖고있는 구조라면 this는 같은 값을 가리키게 되어 종종 "그게 그거 아니야?" 와 같은 혼란을 가중시키게 됩니다.
class Example {
foo() {
console.log(this);
}
bar = () => {
console.log(this);
}
}
const example = new Example();
const foo = example.foo();
const bar = example.bar();
console.log(foo === bar);
/** console output
Example {bar: ƒ}
Example {bar: ƒ}
true
*/
이벤트 바인딩에 따라
함수가 선언된 방식에 따라, 이벤트를 바인딩하는 방법도 달라집니다.
- 일반 함수로 선언한 경우
/* in class */
// good case
bindEvent() {
element.addEventListener(
'click',
this.normalFunction.bind(this)
);
}
normalFunction() {
console.log(this);
}
// bad case
bindEvent() {
element.addEventListener(
'click',
this.normalFunction
);
}
normalFunction() {
console.log(this);
}
여기서 우리가 주목해야 할 부분은 함수 뒤에 붙는 bind(this)
입니다.
일반 함수로 선언했을때, 함수 내의 this
는 해당 함수가 호출된 객체와 같다는 사실을 위에서 배웠습니다.
따라서 bind(this)
를 통해 해당 클래스의 스코프를 바인드해주지 않으면, click
이벤트가 일어난 객체를 콘솔에 띄우게 됩니다.
- 화살표 함수로 선언한 경우
/* in class */
bindEvent() {
element.addEventListener(
'click',
this.normalFunction
);
}
normalFunction = () => {
console.log(this);
}
화살표 함수의 this
는 선언된 class의 인스턴스에 종속되어 클래스 내부를 바라보게 됩니다. 따라서 bind()
를 따로 사용해 줄 필요가 없습니다.
bind는 Function의 prototype이기 때문에 화살표 함수에서 사용하면 오히려 오류가 발생합니다.
여기까지 함수와 바인딩, this에 대해 알아보았습니다.
특히 this에 대한 개념을 확실히 알고있지 않으면 의도치 않은 상황에 맞닥뜨리게 될 수도 있으니
이벤트를 바인딩 할 시 항상 주의해서 사용하시면 좋겠습니다.
'이론 > Frontend' 카테고리의 다른 글
Webpack 빠르게 흝어보기 (1) | 2022.03.15 |
---|---|
함수의 호출을 간격을 제한하는 쓰로틀(Throttle) (0) | 2022.03.12 |
node.js에서 명령어로 브라우저 실행하기 (1) | 2022.01.30 |
react에서 <script> 방식으로 js 파일 로드해야 할 때 (0) | 2022.01.11 |
react-canvas-draw 사용법 (4) | 2021.12.26 |
댓글