코어자바스크립트를 필사한 것입니다.
사라진 this
객체 메서드를 콜백으로 전달할 때 this 정보가 사라지는 문제가 생긴다.
객체 메서드가 객체 내부가 아닌 다른 곳에 전달되어 호출되면 this가 사라진다.
let user = {
firstName: "John",
sayHi() {
alert(`Hello, ${this.firstName}!`);
}
};
setTimeout(user.sayHi, 1000); // Hello, undefined!
this.firstName이 "John"이 되어야 하는데, 얼럿 창엔 undefined가 출력된다
이렇게 된 이유는 setTimeout에 객체에서 분리된 함수인 user.sayHi가 전달되기 때문이다.
위 예시의 마지막 줄은 다음 코드와 같다.
let f = user.sayHi;
setTimeout(f, 1000); // user 컨텍스트를 잃어버림
브라우저 환경에서 setTimeout 메서드는 인수로 전달받은 함수를 호출할 때, this에 window를 할당한다. 따라서 위 예시의 this.firstName은 window.firstName이 되는데, window 객체엔 firstName이 없으므로 undefined가 출력된다.
객체 메서드를 실제 메서드가 호출되는 곳으로 전달하는 것은 아주 흔하다. 이 때 컨텍스트를 제대로 유지하려면 어떻게 해야할까?
방법 1: 래퍼
가장 간단한 해결책은 래퍼 함수를 사용하는 것이다.
let user = {
firstName: "John",
sayHi() {
alert(`Hello, ${this.firstName}!`);
}
};
setTimeout(function() {
user.sayHi(); // Hello, John!
}, 1000);
위 예시가 의도한 대로 동작하는 이유는 외부 렉시컬 환경에서 user를 받아서 보통 때처럼 메서드를 호출했기 때문이다.
방법 2: bind
모든 함수는 this를 수정하게 해주는 내장 메서드 bind를 제공한다.
기본 문법은 다음과 같다.
let boundFuc = func.bind(context);
func.bind(context)는 함수처럼 호출 가능한 '특수 객체(exotic object)'를 반환한다. 이 객체를 호출하면 this가 context로 고정된 함수 func이 반환된다.
따라서 boundFunc를 호출하면 this가 고정된 func를 호출하는 것과 동일한 효과를 본다.
아래 funcUser에는 this가 user로 고정된 func이 할당된다.
let user = {
firstName: "John"
};
function func() {
alert(this.firstName);
}
let funcUser = func.bind(user);
funcUser(); // John
'언어 > JavaScript' 카테고리의 다른 글
자바스크립트 객체(Object) (0) | 2021.06.18 |
---|---|
프로토타입 (0) | 2021.05.19 |
DOM 인터페이스와 테스팅 (0) | 2021.05.14 |
DOM (0) | 2021.05.14 |
Document (0) | 2021.05.13 |