자바스크립트의 비밀스러운 삶: 아이덴티티
Source: Dev.to
“점 왼쪽” 규칙
Timothy는 메인 작업대에 있는 의자에 몸을 기대고, 펜을 코드 조각 위에 떨어뜨렸다. 그는 지쳐 보였다.
“이제 더 이상 내가 누군지 모르겠어요, Margaret,” 라고 중얼거렸다.
Margaret는 정리를 멈추고 다가왔다.
“그것은 깊은 철학적 질문이야, Timothy.”
“철학이 아니라 이 함수야,” 라고 그는 종이를 두드리며 말했다. “user객체 안에printName함수를 만들었어. 실행하면 ‘Timothy’가 출력돼. 그런데 그 정확히 같은 함수를 헬퍼에 넘기면, 자신이 누군지 잊어버려.undefined가 출력돼. 정체성 위기를 겪고 있는 거야.”
Margaret는 굴러다니는 칠판을 테이블 위로 끌고 와서 초크를 집었다.
“함수가 위기를 겪는 게 아니라, 당신이
this가 함수에 속한다고 가정하고 있는 거야. 그렇지 않아.”
그녀는 칠판에 큰 함수를 그렸다.
“JavaScript에서
this라는 단어는 고정된 라벨이 아니야. 질문이야. 코드가 실행될 때 함수는 주변을 살피며 ‘누가 나를 호출했는가?’라고 묻는다.”
예시: 메서드 호출
const user = {
name: "Timothy",
speak: function() {
console.log("My name is " + this.name);
}
};
user.speak();
// ^ 점 왼쪽을 보라
// 객체 'user'가 함수를 호출한다.
// 따라서: 'this'는 'user'이다.
“마지막 줄을 봐,” Margaret가 점을 가리키며 말했다. “규칙은 간단해: 점의 왼쪽을 보라.”
“user라는 단어가 있잖아요,” Timothy가 대답했다.
“맞아.user를 통해 호출했기 때문에, 함수는 ‘누가 나를 호출했는가?’라는 질문에 ‘그 사용자’라고 답하는 거야.”
예시: 컨텍스트 상실
Timothy는 버그를 칠판에 적었다.
const myFunction = user.speak;
myFunction();
// ^ 점을 보라
// 점이 없다. 객체도 없다.
// 출력: "My name is undefined"
“내부 코드는 바꾸지 않았어요!” Timothy가 주장했다. “같은 함수잖아요!”
“내부 코드는 변하지 않았어,” Margaret가 동의했다. “하지만 호출 위치가 바뀌었지.”
“myFunction()의 왼쪽을 봐. 점이 있나요? 객체가 있나요?”
“아니요. 그냥 함수 이름이에요.”
“정확히. 점이 없을 때는 함수에 소유자가 없어. 엄격 모드—우리가 항상 쓰는 모드—에서는this가undefined가 돼.”
“그럼 옛날엔 어땠나요?”
“전역window객체가 기본값이었지—재앙을 부르는 레시피였어.”
컨텍스트 강제 지정
.call()을 이용한 일회성 호출
const stranger = { name: "Margaret" };
// 우리는 지금 `speak`가 `stranger`를 `this`로 사용하도록 강제한다
user.speak.call(stranger);
// 출력: "My name is Margaret"
“
.call()을 쓰면 함수에게 ‘네가 어디에 있든 상관없어. 이번 한 번 실행에서는 네 정체성을 이 객체로 삼아라’고 말하는 거야.”
.bind()를 이용한 영구 바인딩
// 우리는 `user`에 영구적으로 고정된 새로운 함수를 만든다
const boundFunction = user.speak.bind(user);
boundFunction();
// 출력: "My name is Timothy" (영원히)
“
.bind()는 함수를 실행하지 않아. 함수의 복사본을 반환하는데, 이 복사본은 소유자를 영원히 기억해. 나중에 어떻게 호출하든this는 항상user가 돼.”
요약
- 점이 있나요? →
this는 왼쪽에 있는 객체다. - 점이 없나요? →
this는undefined(엄격 모드) 혹은 전역 객체 (비엄격). .call()이나.bind()를 사용했나요? →this는 명시적으로 지정한 값이다.
“함수가 어디에 존재하는지에 관한 얘기인 줄 알았어요,” Timothy가 인정했다.
“그것은 흔한 실수야,” Margaret가 손에 묻은 초크를 털며 말했다. “JavaScript에서 정체성은 당신이 누군가가 아니라, 당신이 말할 때 누가 당신을 잡고 있느냐에 달려 있어.”