수업을 듣던 중 특정 부분에서 Arrow Function을 사용하면 에러가 발생하는 것을 발견하였다.
과연 Function과 Arrow Function은 무슨 차이가 있길래 이런 현상이 발생하는 것일까?
기본 구문
(param1, param2, …, paramN) => { statements }
(param1, param2, …, paramN) => expression
// 다음과 동일함: => { return expression; }
// 매개변수가 하나뿐인 경우 괄호는 선택사항:
(singleParam) => { statements }
singleParam => { statements }
// 매개변수가 없는 함수는 괄호가 필요:
() => { statements }
예시
var elements = [
'Hydrogen',
'Helium',
'Lithium',
'Beryllium'
];
// 이 문장은 배열을 반환함: [8, 6, 7, 9]
elements.map(function(element) {
return element.length;
});
// 위의 일반적인 함수 표현은 아래 화살표 함수로 쓸 수 있다.
elements.map((element) => {
return element.length;
}); // [8, 6, 7, 9]
// 파라미터가 하나만 있을 때는 주변 괄호를 생략할 수 있다.
elements.map(element => {
return element.length;
}); // [8, 6, 7, 9]
// 화살표 함수의 유일한 문장이 'return'일 때 'return'과
// 중괄호({})를 생략할 수 있다.
elements.map(element => element.length); // [8, 6, 7, 9]
f(); // 6
화살표 함수는 Lexical this를 지원하므로 콜백 함수로 사용하기 편리하다. 하지만 화살표 함수를 사용하는 것이 오히려 혼란을 불러오는 경우도 있으므로 주의하여야 한다.
우선 Arrow Function을 사용하면 안되는 나쁜 예
를 살펴보자.
const cat = {
name: 'bbotto',
sayHi: () => console.log('Hi ${this.name}'),
}
cat.sayHi()
해당 코드를 실행하면 Hi undefined
가 출력된다.
메서드로 정의한 Arrow Function 내부의 this
는 메서드를 소유한 객체, 즉 메서드를 호출한 객체를 가리키지 않고 상위 컨텍스트인 전역 객체 window
를 가리킨다.
다음으로 Function을 사용한 좋은 예
를 살펴보자.
const cat = {
name: 'bbotto',
sayHi() {
console.log('Hi ${this.name}')
},
}
cat.sayHi()
Function을 사용한 코드를 실행하면 Hi bbotto
로 원하는 결과가 출력된다.
화살표 함수로 정의된 메소드를 prototype에 할당하는 경우도 동일한 문제가 발생한다. 화살표 함수로 정의된 메소드를 prototype에 할당하여 보자.
const cat = {
name: 'bbotto',
}
Object.prototype.sayHi = () => console.log(`Hi ${this.name}`)
cat.sayHi()
위 코드를 실행하면 Hi undefined
가 출력된다.
이유는 1번과 마찬가지로 window를 가리키기 때문이다.
const cat = {
name: 'bbotto',
}
Object.prototype.sayHi = function() {
console.log(`Hi ${this.name}`)
}
cat.sayHi()
코드를 실행하면 Hi bbotto
로 원하는 결과가 출력된다.
화살표 함수는 생성자 함수로 사용할 수 없다. 생성자 함수는 prototype 프로퍼티를 가지며 prototype 프로퍼티가 가리키는 프로토타입 객체의 constructor를 사용한다.
하지만 화살표 함수는 prototype 프로퍼티를 가지고 있지 않다.
const Foo = () => {};
// 화살표 함수는 prototype 프로퍼티가 없다
console.log(Foo.hasOwnProperty('prototype')); // false
const foo = new Foo(); // TypeError: Foo is not a constructor
addEventListener 함수의 콜백 함수를 화살표 함수로 정의하면
this
가 상위 컨택스트인 전역 객체window
를 가리킨다.
const $button1 = document.getElementById('button1');
$button1.addEventListener('click', () => {
console.log(this === window); // => true
this.innerHTML = 'Clicked button';
});
this
는 window를 가리킨다.
const $button1 = document.getElementById('button1');
$button1.addEventListener('click', function() {
console.log(this === window); // => false
this.innerHTML = 'Clicked button';
});
일반 함수로 정의된 addEventListener 함수의 콜백 함수 내부의 this
는 이벤트 리스너에 바인딩된 요소(currentTarget)
를 가리킨다.
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Functions/Arrow_functions
https://poiemaweb.com/es6-arrow-function