화살표 함수(Arrow Function)
function
키워드 대신 화살표=>
를 사용해 간략하게 함수를 정의할 수 있다.
표현 뿐 아니라 내부 동작도 기존의 함수보다 간략하다.
특히 콜백 함수 내부에서 this가 전역 객체를 가리키는 문제를 해결하기 위한 대안으로 유용하다.
화살표 함수는 함수 선언문이 아닌 함수 표현식으로 정의해야 한다.
const arrow = () => { ... };
만약 매개변수가 한 개인 경우 소괄호( )
를 생략할 수 있고,
함수 몸체가 표현식인 문 하나로 구성되어 있으면 중괄호{ }
를 생략할 수 있다.
const power = x => x ** 2;
// const power = (x) => { return x ** 2 }; 와 동일함
화살표 함수가 객체 리터럴을 반환하는 경우 소괄호( )
로 감싸주어야 한다.
const person = name => ({
sayHi() {
return `안녕! 내 이름은 ${name}, 탐정이죠.`;
},
});
person('코난').sayHi(); // '안녕! 내 이름은 코난, 탐정이죠.'
또한 화살표 함수를 즉시 실행 함수로도 사용할 수 있다.
const personIIFE = (name => ({
sayHi() {
return `안녕! 내 이름은 ${name}, 탐정이죠.`;
},
}))('코난');
personIIFE.sayHi(); // '안녕! 내 이름은 코난, 탐정이죠.'
화살표 함수와 일반 함수의 차이
화살표 함수는 non-constructor이기 때문에 prototype 프로퍼티가 없고, 프로토타입을 생성하지 않는다.
따라서 생성자 함수로써 호출해 인스턴스를 만들 수 없다.
또 일반 함수가 가지는 함수 자체의 this, arguments, super, new.target 바인딩을 갖지 않는다.
스코프 체인을 통해 상위 스코프에서 화살표 함수가 아닌 함수의 this, arguments, super, new.target을 참조한다.
화살표 함수와 this
화살표 함수가 일반 함수와 구별되는 가장 큰 특징은 this라고 할 수 있다.
this에 바인딩되는 객체는 함수를 정의할 때 정적으로 결정되지 않고, 함수를 호출할 때 동적으로 결정된다.
일반 함수로써 호출되는 모든 함수 내부의 this는 전역 객체를 가리키는데,
화살표 함수는 함수 자체의 this 바인딩을 갖지 않기 때문에 상위 스코프의 this를 그대로 참조한다.
이를 lexical this라고 하는데, 화살표 함수의 this가 함수가 정의된 위치에 따라 결정된다는 것을 의미한다.
이러한 특징 때문에 화살표 함수를 다른 함수의 인수로 전달해 콜백 함수로 사용하는 경우가 많다.
class BadSuffixer {
constructor(suffix) {
this.suffix = suffix;
}
add(arr) {
return arr.map(function (item) {
item + this.suffix;
});
}
}
const badRamenSuffixer = new BadSuffixer('라면');
badRamenSuffixer.add(['참깨', '진']); // TypeError
class Suffixer {
constructor(suffix) {
this.suffix = suffix;
}
add(arr) {
return arr.map((item) => item + this.suffix);
}
}
const ramenSuffixer = new Suffixer('라면');
ramenSuffixer.add(['참깨', '진']); // ['참깨라면', '진라면']
화살표 함수 사용 시 주의할 점
메서드를 화살표 함수로 정의하는 것은 피해야 한다.
const badConan = {
name: '코난',
sayHi: () => console.log(`안녕! 내 이름은 ${this.name}...`),
};
badConan.sayHi(); // '안녕! 내 이름은 ...'
sayHi 프로퍼티에 할당한 화살표 함수 내부의 this는 메서드를 호출한 객체인 badConan 대신 상위 스코프인 전역 객체를 가리키기 때문에, 화살표 함수로 메서드를 정의하는 것은 바람직하지 않다.
메서드를 정의할 때는 ES6 메서드 축약 표현을 사용하는 것이 좋다.
const conan = {
name: '코난',
sayHi() {
console.log(`안녕! 내 이름은 ${this.name}...`);
},
};
conan.sayHi(); // '안녕! 내 이름은 코난...'
Reference>
- 모던 자바스크립트 Deep Dive p.474-483