본문 바로가기
이론/Frontend

함수와 바인딩, this

by 유세지 2022. 3. 3.

이 글은 이 포스트의 연장선에 있습니다.

 

같은 동작을 가진 함수를 바인딩하더라도, 경우에 따라서 실제로는 다른 값을 가지는 경우가 있습니다.

함수의 선언 방식에 따라 이벤트를 어떻게 바인딩하는 것이 좋을지에 대해 알아보겠습니다.

 

this

이벤트에 함수를 바인딩 할 때, this는 특히 신경써야 하는 부분입니다.

this에 대한 정보는 아래 그림처럼 실행 콘텍스트 객체에 포함되어 있습니다.

 

image

 

그러나 호출에 따라 다른 값이 할당되기 때문에 함수 내부 구조만 보고서는 this 값을 정확히 예측하기란 어렵습니다.

때문에 this가 어느 곳을 바라보고 있는지 알아내려면 아래 내용들을 살펴보아야 합니다.

 

함수의 종류에 따라

일반적인 함수와 화살표 함수가 가리키는 this는 서로 다릅니다.

const obj = {
  foo: function () {
    console.log(this);
  },

  bar: () => {
    console.log(this);
  },
}

obj.foo();
obj.bar();

 

obj.foo() 의 경우 thisobj를 가리키고 있지만, 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에 대한 개념을 확실히 알고있지 않으면 의도치 않은 상황에 맞닥뜨리게 될 수도 있으니

이벤트를 바인딩 할 시 항상 주의해서 사용하시면 좋겠습니다.

반응형

댓글