October 15, 2021
setTimeout
에 메서드를 전달할 때처럼, 객체 메서드를 콜백으로 전달할 때 ’this
정보가 사라지는’ 문제가 생깁니다.
이번 챕터에선 이 문제를 어떻게 해결할지에 대해 알아보겠습니다.
앞서 다양한 예제를 통해 this
정보가 사라지는 문제를 경험해보았습니다. 객체 메서드가 객체 내부가 아닌 다른 곳에 전달되어 호출되면 this
가 사라집니다.
아래 funcUser
에는 this
가 user
로 고정된 func
이 할당됩니다.
let user = {
firstName: "John"
};
function func() {
alert(this.firstName);
}
*let funcUser = func.bind(user);
funcUser(); // John*
여기서 func.bind(user)
는 func
의 this
를 user
로 '바인딩한 변형’이라고 생각하시면 됩니다.
인수는 원본 함수 func
에 ‘그대로’ 전달됩니다.
let user = {
firstName: "John",
sayHi() {
alert(`Hello, ${this.firstName}!`);
}
};
*let sayHi = user.sayHi.bind(user); // (*)*// 이제 객체 없이도 객체 메서드를 호출할 수 있습니다.
sayHi(); // Hello, John!
setTimeout(sayHi, 1000); // Hello, John!
// 1초 이내에 user 값이 변화해도
// sayHi는 기존 값을 사용합니다.
user = {
sayHi() { alert("또 다른 사용자!"); }
};
(*)
로 표시한 줄에서 메서드 user.sayHi
를 가져오고, 메서드에 user
를 바인딩합니다. sayHi
는 이제 ‘묶인(bound)’ 함수가 되어 단독으로 호출할 수 있고 setTimeout
에 전달하여 호출할 수도 있습니다. 어떤 방식이든 컨택스트는 원하는 대로 고정됩니다.
아래 예시를 실행하면 인수는 ‘그대로’ 전달되고 bind
에 의해 this
만 고정된 것을 확인할 수 있습니다.
let user = {
firstName: "John",
say(phrase) {
alert(`${phrase}, ${this.firstName}!`);
}
};
let say = user.say.bind(user);
say("Hello"); // Hello, John (인수 "Hello"가 say로 전달되었습니다.)
say("Bye"); // Bye, John ("Bye"가 say로 전달되었습니다.)