November 24, 2021
복잡한 상황에서 메서드를 호출하면 this
값을 잃어버리는 경우가 생깁니다.
예시를 살펴봅시다.
let user = {
name: "John",
hi() { alert(this.name); },
bye() { alert("Bye"); }
};
user.hi(); // John (간단한 호출은 의도한 대로 잘 동작합니다.)
// name에 따라 user.hi나 user.bye가 호출되게 해봅시다.
*(user.name == "John" ? user.hi : user.bye)(); // TypeError: Cannot read property 'name' of undefined*
마지막 줄에서 조건부 연산자를 사용해 user.hi
나 user.bye
중 하나가 호출되도록 했습니다. user의 name이 "John"이므로 user.hi
가 호출될 것이라 예상하며 말이죠.
그런데 에러가 발생했습니다. 뒤에 ()
가 있어서 메서드 hi가 즉시 호출될 것이라 예상했는데 원하는 대로 되지 않았네요.
에러는 메서드를 호출할 때 "this"
에 undefined
가 할당되었기 때문에 발생했습니다.
마지막 줄이 아래와 같았다면 에러 없이 잘 작동했을 겁니다.
user.hi();
그런데 아래 코드에선 에러가 발생하죠.
(user.name == "John" ? user.hi : user.bye)();
원인이 뭘까요? 원인을 알려면 obj.method()
를 호출했을 때, 내부에서 어떤 일이 일어나는지 알아야 합니다.
참조 타입은 자바스크립트 내부에서 사용되는 타입입니다.
.
이나 대괄호를 사용해 객체 프로퍼티인 메서드(obj.method()
)에 접근하려 하면 정확한 프로퍼티 값이 반환되는 것이 아니라 특별한 형태의 값인 ‘참조 타입’ 값이 반한됩니다. 이 참조타입 값엔 프로퍼티 값과 프로퍼티가 정의된 객체 정보가 담겨있습니다.
()
를 사용해 메서드를 호출할 때, 메서드 내에서 사용되는 this
에 제대로 된 객체 정보를 전달해 줄 수 있는 이유가 바로 ‘참조 타입’ 덕분입니다.
그런데 .
이나 대괄호 이외의 연산에선 참조 타입이 그냥 프로퍼티 값으로 변해버립니다. 객체 메서드라면 함숫값으로 변해버리죠.
이런 내부 동작은 보이지 않는 곳에서 일어납니다. 참조 타입이 어떻게 동작하는지 알아야 해결할 수 있는 문제는 표현식을 이용해 동적으로 객체에서 메서드를 가져올 때와 같이 자주 발생하지 않습니다.