[TypeScript] 화살표 함수(Arrow Function)가 대체 뭔가?

자바스크립트를 한번도 사용 해보지 않은 입장에서 무슨 말인지 잘 모르겠다.
this가 어떤 혼란을 야기했길래 그러는 걸까?
(필자는 C, C++ 프로그래밍에 대한 지식은 있음을 참고하자.)
class Person {
name: string;
constructor(name: string) {
this.name = name;
}
sayHello() {
console.log(`Hello, my name is ${this.name}`);
}
sayHelloWithTimeout() {
setTimeout(function() {
console.log(`Hello, my name is ${this.name}`);
}, 1000);
}
sayHelloWithArrowFunctionTimeout() {
setTimeout(() => {
console.log(`Hello, my name is ${this.name}`);
}, 1000);
}
}
const person = new Person("John");
person.sayHello(); // "Hello, my name is John" 출력
person.sayHelloWithTimeout(); // "Hello, my name is undefined" 출력
// sayHelloWithTimeout 함수 내부에서 this는 setTimeout 함수를 호출한 객체가 되므로, undefined가 출력됨.
person.sayHelloWithArrowFunctionTimeout(); // "Hello, my name is John" 출력
// sayHelloWithArrowFunctionTimeout 함수 내부에서 this는 상위 스코프인 Person 객체가 되므로, 정상적으로 출력됨.
아하..!
C++ 클래스로 생각 해보면 (이 역시 정적 타입 언어, 컴파일 시에 변수의 타입을 결정 하므로 코드를 실행 해보지 않아도 에러가 나는지 알 수 있음)
위의 sayHelloWithTimeout() 이라는 함수 내에서 this.name 이라고 this를 참조 하면 당연히 class Person 의 name 이라는 멤버변수를 참조 할 것이라고 기대될 것인데, 자바스크립트는 이 this를 컴파일 타임이 아니라 실행하는 시점에 참조를 한다.
class Person의 this가 아니라 setTimeout을 호출한 객체(전역 객체)의 this가 되어 버리는 것이다.
그런데 화살표 함수를 쓰면? '해당 함수가 정의 되는 시점에서 함수를 둘러싼 문맥의 this 값으로 고정' 된다.
위의 코드에서는 class Person이 해당 함수를 둘러 싼 문맥 이라고 할 수 있으므로 class Person이 주체인 this로 고정이 된다는 것이다.
이렇게 화살표 함수는 직관적으로 this를 함수 정의 시점의 주변 문맥에서의 this로 고정 시킴으로써 이 this가 실행 시점에는 누구를 주체로 가지게 될지(이해를 위해 이런 표현을 쓰도록 하겠음) 정해지지 않음으로 인한 혼란을 야기 하지 않게 하는 것이다.
자 그럼 맨 위의 사진의 코드는
function getName() {
console.log(this.name);
}
const a = {
name: 'javascript',
getName: getName
};
function getNames() {
a.getName(); // 'javascript'
getName(); // TypeError: Cannot read property 'name' of undefined
}
a.getName() 을 하면 getName을 부른 친구는 a라는 오브젝트이므로 a.name인 'javascript'가 출력이 되는 것이다.
그냥 getName()을 하면? a가 아니라 전역객체의 this를 참조 하게 되므로 undefined 라고 출력이 된다.
사진 내용은 https://ahnheejong.gitbook.io/ts-for-jsdev/02-ecmascript/function/arrow-functions 를 참고했다. 설명이 아주 잘 되어있다!