this 이해하기
호출하는 방식에 따라 this 가 달라지는 것을 봅니다.
this 는 부르는 방식이 정합니다
6.1 에서 this 를 "지금 그 객체" 라고 했습니다. 조금
더 정확히 말하면 this 는 함수를 어떻게 불렀는지에
따라 정해집니다. 함수를 어디에 적었는지가 아닙니다.
이 성질이 버그를 만듭니다. 화살표 함수는 그 문제를 피하려고 규칙이 다릅니다.
점 앞에 있는 것이 this 입니다
const counter = { count: 0, increase() { this.count++; return this.count; } }; console.log(counter.increase()); console.log(counter.increase()); console.log(counter.count);
counter.increase() 처럼 부르면 점 앞에 있는
것이 this 입니다.
떼어내면 잃습니다
같은 함수를 변수에 담아 부르면 점 앞에 아무것도 없습니다. 그러면
this 도 그 객체가 아닙니다.
const counter = { count: 0, increase() { return ++this.count; } }; console.log(counter.increase()); const increase = counter.increase; console.log(increase()); console.log(counter.count);
NaN 이 나왔고 counter 도
늘지 않았습니다. 떼어낸 함수의 this 는
counter 가 아니라서, 없는 값에
1 을 더한 것입니다(1.6).
이 실수는 오류를 내지 않습니다. 값이 이상할 때까지 모릅니다. 함수를 넘길 일이 많은 4부·5부에서 자주 만납니다.
붙여 두기
bind 는 this 를 정해 둔
새 함수를 만들어 줍니다.
const counter = { count: 0, increase() { return ++this.count; } }; const bound = counter.increase.bind(counter); console.log(bound()); console.log(bound()); console.log(counter.count);
화살표 함수는 다릅니다
화살표 함수는 자기 this 를 만들지 않습니다.
적힌 자리의 바깥 this 를 그대로 씁니다. 그래서
떼어내도 잃지 않습니다.
const timer = { name: "타이머", withFunction() { setTimeout(function () { console.log("보통 함수:", this === timer); }, 10); }, withArrow() { setTimeout(() => { console.log("화살표:", this === timer); }, 10); } }; timer.withFunction(); timer.withArrow();
setTimeout 은 넘겨받은 함수를 점 없이
부릅니다(5.1). 보통 함수는 그때 this 를 잃고,
화살표 함수는 withArrow 안의 것을 그대로 씁니다.
다른 함수에 넘길 함수는 화살표로 적으세요. 4.5 의
addEventListener 도 같습니다.
메서드는 화살표로 적지 않습니다
반대로 객체의 메서드 자체를 화살표로 적으면 안 됩니다. 바깥에는 그 객체가 없기 때문입니다.
const wrong = { count: 10, read: () => this === wrong }; const right = { count: 10, read() { return this === right; } }; console.log(wrong.read()); console.log(right.read());
정리하면 이렇습니다. 메서드는 보통 함수로, 넘길 함수는 화살표로.
처음에 자주 걸리는 것
setTimeout(counter.increase, 100) 은 점 없이
불립니다. bind 하거나 화살표로 감싸세요.
setTimeout(counter.increase, 100); // this 를 잃습니다 setTimeout(() => counter.increase(), 100); // 이렇게 적습니다
바깥에 그 객체가 없어 this 가 엉뚱한 것을
가리킵니다. 클래스 메서드도 마찬가지입니다.
this 를 잃어도 대개 오류가 아니라
undefined 나 NaN 이
나옵니다. 값이 이상하면 이것을 먼저 의심하세요.
직접 해보기
아래 두 줄의 결과를 먼저 적어 보고 확인하세요.
홍길동님, 둘째 줄은 this 를 잃어 이름이 비어 있습니다.아래 코드는 0.1초 뒤 이름을 출력하려 했는데 그러지 못합니다. 두 가지 방법으로 고쳐 보세요.
이 단원의 정리
this는 함수를 어떻게 불렀는지가 정합니다.객체.메서드()로 부르면 점 앞의 것이this입니다.- 떼어내 부르면 잃습니다. 오류가 나지 않아 알아채기 어렵습니다.
- 화살표 함수는 자기
this를 만들지 않고 바깥 것을 씁니다. - 메서드는 보통 함수로, 넘길 함수는 화살표로 적습니다.