this 값이 undefined인 함수 고치기
중요도: 5
아래 함수 askPassword()
는 비밀번호를 먼저 확인하고 그 결과에 따라 user.loginOk
나 user.loginFail
을 호출해야 합니다.
그런데 함수를 호출하면 에러가 발생합니다. 에러는 왜 발생했을까요?
에러가 발생하지 않도록 색칠된 줄을 고쳐보세요. 다른 줄은 바꾸지 않아야 합니다.
function askPassword(ok, fail) {
let password = prompt("비밀번호를 입력해주세요.", '');
if (password == "rockstar") ok();
else fail();
}
let user = {
name: 'John',
loginOk() {
alert(`${this.name}님이 로그인하였습니다.`);
},
loginFail() {
alert(`${this.name}님이 로그인에 실패하였습니다.`);
},
};
askPassword(user.loginOk, user.loginFail);
에러는 ask
가 함수 loginOk
, loginFail
을 객체 없이 가지고 오기 때문에 발생합니다.
ask는 loginOk
, loginFail
을 호출할 때 this=undefined
라고 자연스레 가정합니다.
bind
함수를 사용해 컨텍스트를 고정시켜 봅시다.
function askPassword(ok, fail) {
let password = prompt("비밀번호를 입력해주세요.", '');
if (password == "rockstar") ok();
else fail();
}
let user = {
name: 'John',
loginOk() {
alert(`${this.name}님이 로그인하였습니다.`);
},
loginFail() {
alert(`${this.name}님이 로그인에 실패하였습니다.`);
},
};
askPassword(user.loginOk.bind(user), user.loginFail.bind(user));
이제 잘 동작합니다.
이 외에도 다른 답이 있는데, 아래에서 확인 가능합니다.
//...
askPassword(() => user.loginOk(), () => user.loginFail());
이렇게 화살표 함수를 사용하는 방법 또한 대개 잘 동작하며 가독성도 좋습니다.
다만 이 방법은 askPassword
가 호출됐으나 사용자가 프롬프트 대화상자에 값을 제출하고 () => user.loginOk()
를 호출하기 전에 user
변수가 바뀌는 등의 복잡한 상황에서는 오작동할 가능성이 있습니다.