화살표 함수(Arrow Function)
화살표 함수(Arrow function)는 function 키워드 대신 화살표(=>)를 사용하여 보다 간략한 방법으로 함수를 선언할 수 있다는 장점이 있는데, 아무 때나 사용할 수 있는 것은 아닙니다. 화살표 함수의 기본 문법은 다음과 같습니다.
// 매개변수 지정 방법
() => { ... } // 매개변수가 없을 경우
x => { ... } // 매개변수가 한 개면, 소괄호 생략가능
(x, y) => { ... } // 매개변수가 여러 개면, 소괄호 생략불가
// 함수 몸체 지정 방법
x => { return x * x } // single line block
x => x * x
// 함수 몸체가 한줄이면 중괄호를 생략가능.
// 암묵적으로 return된다. 위 표현과 동일하다.
() => { return { a: 1 }; }
() => ({ a: 1 })
// 위 표현과 동일하다. 객체 반환시 소괄호를 사용한다.
() => { // multi line block.
const x = 10;
return x * x;
};
화살표 함수의 호출
화살표 함수는 익명 함수로만 사용할 수 있습니다. 따라서 화살표 함수는 아래와 같이 사용할 수 있습니다.
// ES6의 경우
const pow = x => x * x;
console.log(pow(10)); // 100
또는 콜백 함수로 사용할 수 있는데요, 이 경우 일반적인 함수 선언식보다 간결하게 사용이 가능합니다.
// 선언식
const arr = [1, 2, 3];
const pow = arr.map(function (x) {
return x * x;
});
console.log(pow); // [ 1, 4, 9 ]
// 표현식
const arr = [1, 2, 3];
const pow = arr.map(x => x * x);
console.log(pow); // [ 1, 4, 9 ]
어떤가요? 훨씬 간결하죠?
this
위와 같은 표현적인 차이도 있지만, function 키워드로 생성한 일반 함수와 화살표 함수의 가장 큰 차이점은 this
입니다.
일반 함수의 this
자바스크립트의 경우 함수 호출 방식에 의해 this에 바인딩할 어떤 객체가 동적으로 결정됩니다. 다시 말해, 함수를 선언할 때 this에 바인딩할 객체가 정적으로 결정되는 것이 아니고, 함수를 호출할 때 함수가 어떻게 호출되었는지에 따라 this에 바인딩할 객체가 동적으로 결정된다는 뜻이죠.
일단 아래의 코드를 봅시다.
function Prefixer(prefix) {
this.prefix = prefix;
}
Prefixer.prototype.prefixArray = function (arr) {
// (A)
return arr.map(function (x) {
return this.prefix + ' ' + x; // (B)
});
};
const pre = new Prefixer('Hi');
console.log(pre.prefixArray(['Lee', 'Kim']));
(A) 지점에서의 this는 생성자 함수 Prefixer가 생성한 객체, 즉 생성자 함수의 인스턴스(위 예제의 경우 pre)이다.
(B) 지점에서 사용한 this는 아마도 생성자 함수 Prefixer가 생성한 객체(위 예제의 경우 pre)일 것으로 기대하였겠지만, 이곳에서 this는 전역 객체 window를 가리킨다. 이는 생성자 함수와 객체의 메소드를 제외한 모든 함수(내부 함수, 콜백 함수 포함) 내부의 this는 전역 객체를 가리키기 때문이다.
위 설명이 잘 이해되지 않는다면 this를 참조하길 바랍니다. 이 블로그는 정리가 매우 잘 되어 있어서 저도 가끔 개념이 헷갈릴 때면 찾아가서 들여다보고는 하거든요.
콜백 함수 내부의 this가 메소드를 호출한 객체(생성자 함수의 인스턴스)를 가리키게 하려면 [bind](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Function/bind)
메소드를 사용하면 됩니다.
function Prefixer(prefix) {
this.prefix = prefix;
}
Prefixer.prototype.prefixArray = function (arr) {
return arr.map(function (x) {
return this.prefix + ' ' + x;
}.bind(this)); // this: Prefixer 생성자 함수의 인스턴스
};
const pre = new Prefixer('Hi');
console.log(pre.prefixArray(['Lee', 'Kim']));
화살표 함수의 this
위와 같이 일반 함수는 함수를 선언할 때 this에 바인딩할 객체가 정적으로 결정되는 것이 아니고, 함수를 호출할 때 함수가 어떻게 호출되었는지에 따라 this에 바인딩할 객체가 동적으로 결정됩니다. 그럼 화살표 함수에서는 어떻다는 걸까요?
화살표 함수에서는 함수를 선언할 때
this에 바인딩할 객체가 정적으로 결정됩니다. 동적으로 결정되는 일반 함수와는 달리 화살표 함수의 this 언제나 상위 스코프의 this를 가리키며, 이를 Lexical this라 합니다.
화살표 함수의 this 바인딩 객체 결정 방식은, 함수의 상위 스코프를 결정하는 방식인 렉시컬 스코프와 유사합니다. 렉시컬 스코프에 대해서라면 다음 기회에 상세하게 설명해보도록 하겠습니다.