화살표 함수는 function 키워드 대신 화살표 (⇒)를 사용하여 간결한 문법으로 함수를 생성하는 것을 의미한다.
// 기존 함수
const foo = function () {
console.log('기존 함수');
}
// 화살표 함수
const foo = () => console.log('화살표 함수');
함수에다 인자를 추가하여 생성하고 싶다면 다음과 같다.
// 기존 함수
const foo = function (a,b) {
console.log(a,b);
}
// 화살표 함수
const foo = (a.b) => console.log(a,b);
화살표 함수와 일반 함수의 차이는 다음과 같다.
이러한 제약들에도 불구하고 화살표 함수를 사용하는 이유는 this의 바인딩에 차이가 있어 많이 사용한다.
이는 일반 함수에서 “콜백 함수 내부의 this 문제”를 해결할 수 있기 때문에 의도적으로 설계되었다.
Javascript에서 this 바인딩
javascript에서 함수 호출시 함수 내부의 this는 지정되지 않고 전역 객체가 되기 때문에 문제점이 발생한다.
예를 들면 다음과 같다.
class Prefixer{
constructor(prefix)
{
this.prefix = prefix;
}
add(arr)
{
return arr.map(function (item) {
return this.prefix + item;
// Type Error
});
}
}
const prefix = new Prefix('-webkit-');
console.log(prefixer.add(['transition', 'user-select']
해당 문제점을 해결하기 위해서는 this를 일단 회피시키거나 this를 같이 넣어주거나, bind 함수를 적용하여 해결했다.
add(arr)
{
const that = this;
return arr.map(function (item) {
return that.prefix + item;
});
}
add(arr)
{
const that = this;
return arr.map(function (item) {
return that.prefix + item;
},this);
}
add(arr)
{
const that = this;
return arr.map(function (item) {
return that.prefix + item;
}.bint(this));
}
이 방법들 외에도 화살표 함수를 사용하면 해당 문제점을 쉽게 해결할 수 있다. 화살표 함수는 함수 자체의 this 바인딩을 갖지 않고 있기 때문에 화살표 함수 내부에서 this를 참조하면 상위 스코프의 this를 그대로 참조한다.
add(arr)
{
return arr.map(item => this.prefix + item);
}
즉 화살표 함수에는 this가 없기 때문에 내가 의도한대로 사용 가능
만약 화살표 함수가 중첩되어 있다면 상위 화살표 함수에도 this 바인딩이 없으므로 스코프 체인 상에서 가장 가까운 상위 함수에서 화살표 함수가 아닌 함수의 this 를 참조한다.
(function () {
const bar = () => () => console.log(this);
bar()();
}).call({a:1});
const person = {
name : 'Lee',
sayHi : () => console.log(`Hi ${this.name}); // Hi
}
이때 클래스 필드 정의 제안을 사용하여 클래스 필드에 화살표 함수를 할당하면 해당 문제점이 해결되지만 바람직하지 않다.
const person = {
name : 'Lee',
sayHi = () => console.log(`Hi ${this.name}); // Hi Lee
}
바람직하지 않는다는데 고집 부리지 말고 메서드 구현시 일반 함수 사용하자
const Foo = () => {};
new Foo(); // TypeError
const arrow = (a,a) => a + a; // TypeError