Skip to content

화살표 함수

ES6가 도입되면서, js에 화살표 함수라는 문법이 등장했다. 화살표 함수는 말 그대로 화살표(=>) 표시를 사용해서 함수를 선언하는 방법이다.

// 기존 함수
const foo = function () {
console.log('기존 함수');
}
// 화살표 함수
const foo = () => console.log('화살표 함수');

두 코드는 기능적으로 완전히 동일하게 작동한다. 그러나, 두 코드는 this 바인딩에서 차이가 있다.

this 바인딩

JS의 this는 상황에 따라 다르게 바인딩 된다. 대표적으로 this에 바인딩되는 값들은 이렇다.

전역 공간의 this : 전역 객체
메소드 호출 시 메소드 내부의 this : 해당 메소드를 호출한 객체
함수 호출 시 함수 내부의 this : 지정되지 않음

여기서 자세히 살펴봐야하는 것은 함수에 대한 부분이다. 함수를 호출했을 때 그 함수 내부의 this는 지정되지 않는다. 그리고 this가 지정되지 않은 경우, this는 자동으로 전역 객체를 바라보기 때문에 함수를 호출하면 함수 내부에서의 this는 전역 객체가 된다고 정리할 수 있다.

즉, 그냥 함수를 호출한다면 다음과 같은 상황이 연출된다.

const cat = {
name: 'meow',
foo1: function() {
const foo2 = function() {
console.log(this.name);
}
foo2();
}
};
cat.foo1(); // undefined
  • cat.foo1() 메소드 호출 시 내부 함수 foo2가 실행됨
  • 함수가 호출됐으므로 foo2 내부의 this는 지정되지 않아서 곧 전역 객체를 가리킴
  • 전역 객체에 name이란 속성은 존재하지 않으므로 undefined가 뜸

그러나 화살표 함수는 this로 지정된 값이 없기 때문에 선언될 시점에서의 상위 스코프가 this로 바인딩된다. 그렇기 때문에 화살표 함수를 사용하면 this가 cat 객체를 가리키도록 할 수 있다.

const cat = {
name: 'meow',
foo1: function() {
const foo2 = () => {
console.log(this.name);
}
foo2();
}
};
cat.foo1(); // meow

화살표 함수를 사용하면 안되는 경우

화살표 함수도 사용해선 안되는 때가 있다. 상위 환경의 this를 참조한다는 점이 문제가 될 수도 있다. 바로 다음과 같은 경우이다.

1. 메소드

const cat = {
name: 'meow';
callName: () => console.log(this.name);
}
cat.callName(); // undefined

이 같은 경우, callName 메소드의 this는 자신을 호출한 객체 cat이 아니라 함수 선언 시점의 상위 스코프인 전역객체를 가리키게 된다.

2. 생성자 함수

const Foo = () => {};
const foo = new Foo() // TypeError: Foo is not a constructor

화살표 함수는 생성자 함수로 사용할 수 없게 만들어졌기 때문에, 이와 같이 사용하면 에러가 발생한다.

3. addEventListener()의 콜백함수

const button = document.getElementById('myButton');
button.addEventListener('click', () => {
console.log(this); // Window
this.innerHTML = 'clicked';
});
button.addEventListener('click', function() {
console.log(this); // button 엘리먼트
this.innerHTML = 'clicked';
});

원래 addEventListener의 콜백함수에서는 this에 해당 이벤트 리스너가 호출된 엘리먼트가 바인딩되도록 정의되어 있다. 이처럼 이미 this의 값이 정해져있는 콜백함수의 경우, 화살표 함수를 사용하면 기존 바인딩 값이 사라지고 상위 스코프(이 경우엔 전역 객체)가 바인딩되기 때문에 의도했던대로 동작하지 않을 수 있다.

물론 상위 스코프의 속성들을 쓰려고 의도한 경우라면 사용할 수 있다.


참고