화살표 함수(Arrow Function)은 ES6 문법에서 함수를 표현하는 새로운 방식입니다. 기존의 function 키워드 대신 화살표(=>)를 사용하여 간략하게 표현할 수 있습니다.
setTimeout(function() {
console.log('hello world');
},1000);
setTimeout(() => {
console.log('hello world');
},1000);
위 2개의 코드는 동일한 작업을 수행합니다. 콘솔창에 'hello world'를 출력합니다.
이런 경우에는 두 문법간의 차이점이 없어 보입니다.
그러면 화살표함수가 기존의 함수선언 문법을 완전히 대체할 수 있는걸까요?
결론부터 말씀드리면 답은 'No'입니다.
화살표 함수가 기존의 Fucntion 키워드를 활용하는 함수 선언 방식을 완전히 대체하지는 않습니다. 사용용도가 조금 다릅니다. 화살표 함수 표현법은 주로 함수를 파라미터로 전달할 때 유용합니다. 그러나 이 글에서는 화살표 함수가 어떻게 사용되는지 보다는 기존 함수와의 차이점에 주목하여 작성하겠습니다. 화살표 함수의 표현법이나 활용은 다른 훌륭한 분들이 게시한 글들이 많으니 그 글들을 참고해 주시면 감사하겠습니다.
화살표 함수와 기존의 함수 선언법의 차이 중 가장 큰 차이는 서로 가리키고 있는 this 값이 다르다는 점 입니다.
아래 예제를 통해 확인해보겠습니다.
function BlackCat() {
this.name = '흰냥이';
return {
name: '깜냥이',
crying: function() {
console.log(this.name + ' : 냐옹');
}
}
}
const blackCat = new BlackCat();
blackCat.crying(); //깜냥이 : 냐옹
function WhiteCat() {
this.name = '흰냥이';
return {
name:'깜냥이',
crying : () => {
console.log(this.name + ' : 냐옹')
}
}
}
const whiteCat = new WhiteCat();
whiteCat.crying(); // 흰냥이 : 냐옹
function 을 사용했을 때는 this.name 은 깜냥이를 가리키고, () => 를 사용했을 때는 this.name 이 흰냥이를 가리킵니다.
function 은 자신이 종속된 객체를 this로 가리키며, 화살표 함수는 자신이 종속된 인스턴스를 this로 가리킵니다.
일반적으로, 자바스크립트의 this는 동적으로 어떻게 호출되었는 지에 따라서 결정됩니다.
그러나 화살표 함수의 this 는 함수를 선언할 때 정적으로 바인딩 할 객체가 정해집니다. 화살표 함수의 this는 언제나 상위 스코프의 this를 가리킵니다. 이를 Lexical this 라고 합니다.
위 예제에서 this를 호출하는 대상은 crying 입니다. 따라서 일반 함수가 가리키는 this는 동일 scope인 깜냥이가 되는 것이고, 화살표 함수가 가리키는 this는 상위 스코프인 whiteCat 객체의 name인 흰냥이가 되는것이죠.
위와 같은 화살표 함수의 Lexical this 때문에 화살표 함수를 사용하면 안되는 곳이 있습니다.
1.메소드 정의
//Bad
const cat = {
name : '흰냥이',
crying : () => console.log(`${this.name} 야옹`)
};
cat.crying();
위 예제에서 this 는 함수를 호출한 객체인 cat을 가리키지 않고 그 상위 컨텍스트 요소인 전역 객체 window를 가리키게 되어서 의도하는 대로 동작하지 않습니다.
이 경우에는 아래 처럼 ES6의 축약기법을 활용하는 것이 좋습니다.
//Good
const cat = {
name : '흰냥이',
crying() { console.log(`${this.name} 야옹`)}
}
cat.crying();
2.prototype
const cat = {
name : '야옹이'
}
Object.prototype.crying = () => console.log(`${this.name} 냐옹`);
cat.crying(); // undefined
화살표 함수로 정의된 메소드를 prototype에 할당하는 경우에도 마찬가지입니다.
this.name이 undefined 라서 의도한 대로 동작하지 않습니다. prototype의 경우에도 일반함수로 할당해 주어야 합니다.
3.constructor
화살표 함수는 생성자 함수로 사용할 수 없습니다. 왜냐하면, 생성자함수는 prototype 프로퍼티를 가지고 있는데, prototype이 가리키는 객체의 constructor를 사용하지만, 화살표 함수는 prototype 프로퍼티를 가지고 있지 않습니다.
const Foo = () => {};
// 화살표 함수는 prototype 프로퍼티가 없다
console.log(Foo.hasOwnProperty('prototype')); // false
const foo = new Foo(); // TypeError: Foo is not a constructor
4.addEventListener 함수의 콜백 함수
const btn = document.getElementById('myBtn');
btn.addEventListener('click',() => {
console.log(this === window); // true
});
addEventListener 함수의 콜백 함수를 화살표 함수로 정의하면 this는 상위 컨택스트 전역 객체 window를 가리킵니다.
이 경우에도 콜백함수에서 this를 사용하려면 일반 함수로 정의해야 합니다. 일반함수로 정의한 콜백함수 내부에서 this는 이벤트 리스너에 바인딩된 요소(event.target)을 가리킵니다.
두번째 차이점은 화살표 함수는 오직 익명함수로만 표현이 가능합니다. 일반 함수표현식에서는 아래 코드처럼 함수가 이름을 가질 수 있지만 화살표함수는 파라미터만 설정 가능할 뿐 함수의 이름을 표현하지 못합니다.
function hasNameFunction() { doSomething }
React의 hooks 공부를 하며 실습하다가 문득 일반 함수와 화살표 함수의 차이를 분명 공부했는데 두루뭉실해서 이번 기회에 정리해야겠다는 생각으로 포스팅했습니다.
'JavaScript' 카테고리의 다른 글
함수의 파라미터로 함수를 전달할 때 표현법에 따른 차이 (0) | 2019.11.13 |
---|