(2024-02-17 보완)
this
JavaScript에서 함수를 정의하는 두 가지 방법
function
키워드를 사용하는 방법이 두 가지 방법은 this
에서 차이가 있다.
object의 메서드를 두 가지 방법으로 구현해 보겠다.
const objectA = {
logThis: () => console.log(this) // 화살표 사용 방법
}
const objectB = {
logThis: function() { // `function` 키워드 사용 방법
console.log(this);
}
}
objectA.logThis(); // Window {0: global, window: Window, self: Window, document: document, name: '', location: Location, …}
objectB.logThis(); // {logThis: ƒ}
function
키워드를 사용한 logThis()
는 자체적으로 this
를 바인딩한 반면,
화살표를 사용한 logThis()
는 objectA
의 this
를 그대로 이어받았다. 다시 말해, 부모 스코프(또는 lexical scope)의 this
를 이어받은 것.
(참고로, 브라우저 콘솔의 경우 최상위 스코프의 this
는 window
)
덧붙이면,
counter.increment()
과 같은 식으로 호출될 때,
.
오른쪽의 함수 increment()
가 function
키워드를 사용한 함수라면,
increment()
함수 안에서의 this
는 .
왼쪽에 있는 counter
가 되는 것.
따라서, 아래처럼 this
를 사용해야 하는 경우에는 function
키워드를 사용해야 한다.
const counter = {
count: 0,
increment() { // `function` 키워드 사용 방법에서 키워드를 생략한 축약 표현
this.count += 1;
}
}
console.log(counter.count); // 0
counter.increment();
counter.increment();
console.log(counter.count); // 2
의도대로 increment()
가 counter
의 count
를 잘 증가시킨다.
그런데 이때, counter
의 increment()
만 필요해서 따로 변수에 할당하면 어떻게 될까?
const incrementCount = counter.increment;
console.log(counter.count); // 0
incrementCount();
incrementCount();
console.log(counter.count); // 0
의도대로 동작하지 않는다. this
가 달라졌기 때문이다. (함수에서 로그를 찍어 보면 확인 가능)
increment()
함수의 this
가 counter
(에 할당한 object)지만,
incrementCount()
함수의 this
는 Window
가 되었다.
참고로, 실무에서 나는 코드를 좀 더 안전하게 짜겠다고 PrismaClient
의 일부 메서드만 리포지토리의 프로퍼티로 복사하다가 이런 문제를 겪음.
bind()
그럼 this
를 유지하려면 어떻게 해야 할까?
아래처럼 .bind()
를 사용하면 된다.
const incrementCount = counter.increment.bind(counter);