6.10 함수 바인딩

class 안에 있는 함수를 콜백으로 전달할 때, 'this'의 정보 (클래스의 정보)가 사라지는 문제가 생긴다. 객체 메서드가 객체 내부가 아닌 다른 곳에 전달되어 호출되면 this가 사라진다.

setTimeout method는 브라우저 환경에서 인수로 전달받은 callback 함수를 호출할 때, this에 window를 할당한다. (Node.js 환경에서는 this가 타이머 객체가 된다.) 따라서 위 예시의 this.firstName은 window.firstName이 되는데, window 객체엔 firstName이 없으므로 undefined가 출력된다.

메서드를 전달할 때, 콘텍스트도 같이 유지하는 방법은?

방법 1: rapper

위 예시가 의도한 대로 동작하는 이유는 외부 렉시컬 환경에서 user를 받아서 보통 때처럼 메서드를 호출했기 때문이다. 강조 표시한 줄은 아래와 같이 arrow function으로 변경할 수도 있다.

방법 2: arrow function

이렇게 코드를 작성하면 간결해서 보기는 좋지만, 약간의 취약성이 생긴다. setTimeout이 트리거 되기 전에 (1초가 지나기 전에) user가 변경되면, 변경된 객체의 메서드인 sayHi()를 호출하게 된다.

다음 방법을 사용하면 이런 일이 발생하지 않는다.

방법 3: bind

모든 함수는 this를 수정하게 해주는 내장 메서드 bind를 제공한다.
let boundFunc = function.bind(context);

function.bind(context)는 함수처럼 호출 가능한 특수 객체(exotic object)를 반환한다. 이 객체를 호출하면 this가 context로 고정된 함수 fucntion이 반환된다. 따라서 boundFonc을 호출하면 this가 고정된 function을 호출하는 것과 동일한 효과를 본다.

this.field.addEventListener('click', this.onClick);

// option 1: doesn't work well
// this.onClick = this.onClick.bind(this);

// option 2: work
// this.field.addEventListener('click', (event) => {
//   this.onClick(event);
// });

// option 3: change the onClick function as shown below
// onClick = (event) => {}

좋은 웹페이지 즐겨찾기