JavaScript 화살표 함수
JavaScript ES6의 화살표 함수에 대해 알아보겠습니다.
1. 화살표 함수
화살표 함수는 ES6에서 도입된 문법입니다. function 키워드를 사용하는 것보다 간결하고 항상 익명으로 동작합니다.
1.1. 화살표 함수 선언
화살표 함수의 매개변수를 지정하는 방법입니다.
1
2
3
4
5
6
7
8
|
// 매개변수가 없는 경우
var arrowFunc = () => { ... };
// 매개변수가 한 개인 경우 (소괄호를 생략 가능)
var arrowFunc = x => { ... };
// 매개변수가 여러 개인 경우 (소괄호를 생략 불가)
var arrowFunc = (x, y) => { ... };
|
cs |
화살표 함수의 block을 지정하는 방법입니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
// block 내용이 한 줄인 경우
var arrowFunc = x => { return x * x };
// block 내용이 한 줄인 경우
// 중괄호, return 생략 가능
var arrowFunc = x => x * x;
// block 내용이 한 줄인 경우 (객체)
var arrowFunc = () => { return { a: 1 }; };
// block 내용이 한 줄인 경우 (객체)
// 중괄호, return 생략 가능
// 객체 반환시 반드시 소괄호 사용
var arrowFunc = () => ( { a: 1 } );
// block 내용이 여러 줄인 경우
// 중괄호 생략 불가
var arrowFunc = (x, y) => {
const z = 10;
return x * y * z;
};
|
cs |
화살표 함수의 block 내에 여러 줄의 코드를 작성한 경우엔 반드시 중괄호를 사용해줘야 합니다. 또한 이와 같이 중괄호를 사용한 경우엔 return 생략이 불가능하다는 특징이 있습니다.
1.2 화살표 함수 호출
화살표 함수는 익명으로만 사용할 수 있기 때문에 다음과 같이 함수 표현식을 사용하여 호출합니다.
1
2
3
4
5
6
7
8
9
|
// ES5
var func = function (x, y) {
return x * y;
};
// ES6
const func = (x, y) => {
return x * y
};
|
cs |
또한 콜백 함수에도 사용할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
var arr = [1, 2, 3];
// ES5
var func = arr.map(
function (x) {
return x * x;
}
);
// ES6
const func = arr.map(
(x) => {
return x * x;
}
);
|
cs |
2. this
일반 함수와 화살표 함수의 this는 차이점이 있습니다. 일반 함수의 this는 전역 객체 window를 의미하고 화살표 함수에서는 상위 스코프의 this를 의미합니다.
2.1. 일반 함수의 this
1
2
3
4
5
6
7
8
9
10
11
12
|
const marine = {
action: 'attack',
operation: function() {
console.log(this); // 1. marine 객체
setTimeout(function() {
console.log(this); // 2. window 객체
console.log(this.action); // 3. undefined
}, 1000);
}
};
marine.operation();
|
cs |
위의 예제를 확인해보면 1번의 this는 marine을 나타냅니다. 2번의 this는 내부 함수인 콜백 함수에서 호출되어 window 객체를 나타내는데, 그렇기 때문에 3번의 경우 정의되지 않은 프로퍼티를 참조할 수 없어서 undefined가 출력되게 됩니다.
화살표 함수를 사용하면 위와 같은 문제가 해결되지만 화살표 함수 없이 해결하기 위해선 다음의 방법을 이용합니다.
콜백 함수 안에서 사용할 수 있도록 this를 할당한 that 변수를 지정해줍니다.
1
2
3
4
5
6
7
8
9
10
11
|
const marine = {
action: 'attack',
operation: function() {
const that = this; // marine 객체
setTimeout(function() {
console.log(that.action); // attack
}, 1000);
}
};
marine.operation();
|
cs |
다음과 같이 bind()에 this를 지정해주는 방법도 있습니다.
1
2
3
4
5
6
7
8
9
10
|
const marine = {
action: 'attack',
operation: function() {
setTimeout( function() {
console.log(this.action); // attack
}.bind(this), 1000);
}
};
marine.operation();
|
cs |
마지막으로 map()을 사용할 때 this를 넘겨주는 방법이 있습니다.
1
2
3
4
5
6
7
8
9
10
11
|
const action: string [] = ['attack', 'move', 'stop'];
const marine = {
operation: function() {
action.map(function(item){
console.log(item);
}, this);
}
};
marine.operation();
|
cs |
2.2. 화살표 함수의 this
일반 함수와는 다르게 화살표 함수는 선언할 때 this에 바인딩할 객체가 정적으로 결정됩니다. 화살표 함수의 this는 항상 상위 스코프의 this를 가리키는데 이를 Lexical this 라고 합니다.
1
2
3
4
5
6
7
8
9
10
11
|
const action: string [] = ['attack', 'move', 'stop'];
const marine = {
operation: function() {
action.map(item => {
console.log(item);
});
}
};
marine.operation();
|
cs |
앞서 확인한 일반 함수의 콜백 함수를 화살표 함수로 변경한 예제입니다. 실행하면 action[]의 값이 출력되는 것을 확인할 수 있습니다.
3. 화살표 함수를 사용하면 안되는 경우
다음은 화살표 함수를 사용하면 안되는 경우입니다.
3.1 메소드
다음 예제처럼 메소드를 화살표 함수로 정의하면 함수 내부의 this는 window 객체를 가리키기 때문에 문제가 발생합니다.
1
2
3
4
5
6
7
8
|
const marine = {
action: 'attack',
operation: () => {
console.log(this.action); // undefined
}
};
marine.operation();
|
cs |
이런 경우엔 다음과 같이 ES6의 축약 메소드를 사용하는 것이 좋습니다.
1
2
3
4
5
6
7
8
|
const marine = {
action: 'attack',
operation() {
console.log(this.action); // attack
}
};
marine.operation();
|
cs |
3.2 프로토타입 (prototype)
화살표 함수로 정의한 메소드를 prototype에 할당하는 경우에도 같은 문제가 발생합니다.
1
2
3
4
5
6
7
8
9
|
const marine = {
action: 'attack'
};
Object.prototype.operation = () => {
console.log(this.action); // undefined
};
marine.operation();
|
cs |
이러한 경우엔 화살표 함수 대신 일반 함수를 이용하여 할당해줍니다.
1
2
3
4
5
6
7
8
9
|
const marine = {
action: 'attack'
};
Object.prototype.operation = function() {
console.log(this.action); // attack
};
marine.operation();
|
cs |
3.3 생성자 함수
화살표 함수는 생성자 함수에도 사용할 수 없습니다. 생성자 함수는 prototype 객체의 constructor를 갖고 있는데 화살표 함수는 prototype 프로퍼티를 갖고 있지 않기 때문입니다.
1
2
3
4
5
|
const MarineConstructor = () => {};
console.log(MarineConstructor.hasOwnProperty('prototype')); // false
const marine = new MarineConstructor(); // TypeError: MarineConstructor is not a constructor
|
cs |
3.4 addEventListener()의 콜백 함수
addEventListener()의 콜백 함수를 화살표 함수로 정의하면 화살표 함수 내의 this가 window 객체를 가리키게되어 문제가 발생합니다.
1
2
3
4
5
|
const clickButton = document.getElementById('clickButton');
clickButton.addEventListener('click', () => {
console.log(this === clickButton); // false
});
|
cs |
addEventListener()에서 콜백 함수를 사용할 경우, 내부의 this가 이벤트 리스너에 바인딩된 요소를 가리키도록 다음과 같이 일반 함수로 정의해야 합니다.
1
2
3
4
5
|
const clickButton = document.getElementById('clickButton');
clickButton.addEventListener('click', function() {
console.log(this === clickButton); // true
});
|
cs |
이상으로 JavaScript의 화살표 함수에 대해 알아봤습니다.
※ Reference
- 이웅모 지음, 『Angular Essentials』, 루비페이퍼(2018), p32 ~ p38. 3.3 화살표 함수
- poiemaweb.com, 화살표 함수, https://poiemaweb.com/es6-arrow-function
- velog.io/@ki_blank, JavaScript - 화살표 함수(Arrow function), https://velog.io/@ki_blank/JavaScript-%ED%99%94%EC%82%B4%ED%91%9C-%ED%95%A8%EC%88%98Arrow-function