(ES6) - 03 arrow 함수

  • SUNGMIN SHIN
  • 27 Minutes
  • 2017년 9월 13일

[ ECMA Script6 ]

(http://book.naver.com/bookdb/book_detail.nhn?bid=11556385)


3.1 개요


arrow 함수(이하 화살표 함수)는 함수 선언식( function(param){code} )의 형태를 축약한 것으로 아래와 같은 형식으로 작성합니다.

(param) => { code };
param => { code };
() => { code };
(param1, param2, param3, , , paramN) => { code };
param => ( {key: value} );
(param1, param2, param3, …rest) => { code };
(param1, param2 = 123, , , paramN) => { code };
([one, two] = {1,2}) => one + two;
({key:value} = {key: 10 + 20}) => { code };

화살표 함수는 익명함수로 호출하기 위해서는 함수 표현식과 같이 변수에 할당해야 합니다.

1
let func1 = (param) =>  { code };

화살표 함수는 function 키워드보다 간단하게 선언할 수 있어 편리하지만 모든 경우에 사용할 수 없으며 함수가 실행되는 환경을 고려해야 합니다.


3.2 ES5 형태와 차이


ES5

1
2
3
4
5
6
7
/* [ 소스 arrow - 11 ] */
var es5 = function(one, two) {
return one + two;
}
var sum = es5(1,2);

console.log(sum);

화살표 함수

1
2
3
4
5
6
7
8
9
10
/* [ 소스 arrow - 12 ] */
let arrow1 = (one, two) => {
return one + two
};
let arrow2 = (one, two) => one + two;
let sum1 = arrow1(1,2);
let sum2 = arrow2(1,2);

console.log(sum1);
console.log(sum2);

기능은 동일하고 단지 작성 형태가 다른 코드로 위 코드는 다음의 순서와 방법으로 작성한 것 입니다.

  1. 화살표 함수로 생성한 function 오브젝트를 할당한 변수(es6)를 작성
  2. function 키워드를 사용하지 않음
  3. 소괄호() 안에 파라미터 이름(one, two)을 작성
  4. 이어서 화살표(=>)를 작성
  5. 화살표 앞뒤의 공백은 띄던 붙이던 상관없음
  6. 함수 블록{} 을 작성하고 그 안에 코드를 작성


3.3 블록, 파라미터


화살표 함수는 함수 블럭{}을 사용하지 않고 한 줄에 작성할 수 있습니다.

1
2
3
4
5
6
/* [ 소스 arrow - 21 ] */
// 함수 블록을 사용하지 않은 형태의 화살표 함수
let arrow = (one, two) => one + two;
let sum = arrow(10, 20);

console.log(sum);

화살표 함수 arrow에서 괄호 안의 (one, two)는 파라미터이며 화살표 뒤의 one + two가 return 값으로 return문을 생략한 것입니다. 함수 블럭을 사용하지 않을 경우 화살표 다음에 줄바꿈을 한다면 에러가 발생합니다.

받는 파라미터가 1개라면 소괄호를 제외하고 value만 작성해도 무방합니다.

1
2
3
4
5
6
/* [ 소스 arrow - 22 ] */
// 받는 파라미터가 1개라면 소괄호 생략 가능
let get = value => value + 10;
let result = get(10);

console.log(result);

받는 파라미터가 없다면 소괄호만 작성합니다.

1
2
3
4
5
6
/* [ 소스 arrow - 23 ] */
// 받는 파라미터가 1개라면 괄호 생략 가능
let noParam = () => 3 + 4;
let result = noParam();

console.log(result);


3.4 return


화살표 함수에서 {key: value} 형태의 오브젝트를 반환하려면 소괄호 안에 넣어 작성합니다.

아래 예제는 sports() 함수를 호출하면 {key: value}형태의 빈 오브젝트를 반환 받는 것이 목적 입니다.
하지만 여기서는 undefined가 반환 됩니다. 이는 화살표 다음의 블록{}을 함수 블록으로 인식하고 함수 블록 안에 return 문을 작성하지 않은 것으로 인식하기 때문 입니다.
그리고 다른 함수와 마찬가지로 return문을 작성하지 않으면 기본적으로 undefined를 반환합니다.

1
2
3
4
5
6
7
/* [ 소스 arrow - 31 ] */
// 빈 오브젝트를 반환 받는 화살표 함수 사용의 잘못된 예
let sports = () => {};
let result = sports();

// undefined 반환
console.log(result);

화살표 함수에서 오브젝트를 반환하려면 소괄호() 안에 {}의 형태로 작성합니다. JS는 소괄호 안의 코드를 표현식으로 인식하여 평가하고 평가결과를 반환 합니다.

1
2
3
4
5
6
7
/* [ 소스 arrow - 32 ] */
// 빈 오즈벡트를 반환 받는 화살표 함수의 예
let sports = () => ({});
let result = sports();

// 빈 오브젝트 반환
console.log(result);


3.5 new 연산자


화살표 함수는 new 연산자로 인스턴스를 생성할 수 없습니다
new 연산자를 사용하려면 함수에 prototype이 연결되어 있어야 하고 여기에 constructor가 연결되어 있어야 하지만 화살표 함수로 작성된 함수는 연결되어 있지 않으므로 new 연산자로 인스턴스를 생성할 수 없습니다.

__proto__ 빌트인에 function 오브젝트의 prototype에 연결된 메서드가 첨부됩니다. apply()는 function 오브젝트의 prototype에 연결되어 있습니다. 이 형태는 화살표 함수가 함수라는 것을 의미합니다. 화살표 함수는 함수지만 특별한 형태의 함수 입니다.


3.6 arguments 사용


화살표 함수 블록에서는 arguments 프로퍼티를 사용할 수 없습니다.

arguments 프로퍼티 참고
(https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Functions/arguments)

화살표 함수에서는 아래와 같이 에러가 발생하지는 않지만 사용은 불가능

1
2
3
4
5
6
7
8
9
10
/* [ 소스 arrow-41 ] */
let sports = () => {
try {
let args = arguments;
console.log(args);
} catch(error) {
console.log('사용 불가');
}
};
sports(1,2);

함수 선언문으로는 사용가능

1
2
3
4
5
6
7
8
9
let sports = function() {
try {
let args = arguments;
console.log(args);
} catch(error) {
console.log('사용 불가');
}
};
sports(1,2);

es6에선 arguments 대신 rest 파라미터를 사용합니다. rest파라미터는 ( …rest ) 점 세개를 작성하고 이어서 파라미터 이름 표기하여 작성 합니다. (rest 파라미터에 대한 자세한 내용은 이후에 다룹니다)

1
2
3
4
5
6
7
8
9
10
// rest 파라미터로 임의의 파라미터를 전달 받음
let sports = (...args) => {
try {
// rest 파라미터는 배열 형태로 반환
console.log(args);
} catch(error) {
console.log('사용 불가');
}
};
sports(1,2);

rest 파라미터 참고
(https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Functions/rest_parameters)


3.7 - 3.8 this, setTimeout(), 화살표 함수


화살표 함수는 간단하게 코드를 작성할 수 있어 편리하지만 this의 참조를 고려해야 합니다.

일반 함수에서의 setTimeout()과 this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* [소스 arrow-51] */
let Sports = function() {
this.count = 20;
};
Sports.prototype = {
plus: function() {
this.count+= 1;
},
get: function() {
// 외부에서의 this는 Sports
console.log(this);
setTimeout(function(){
// 내부에서의 this는 window (setTimeout이 window 오브젝트 함수라서)
console.log(this === window);
// window.plus를 참조하기 때문에 undefined(window는 Object이므로)
console.log(this.plus);
}, 1000);
}
};

let newSports = new Sports();
newSports.get();

setTimeout()은 window 오브젝트 함수이므로 setTimeout 내부 함수에서는 this가 window를 참조하게 됩니다.

화살표 함수에서의 setTimeout()과 this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* [소스 arrow-61] */
let Sports = function() {
this.count = 20;
};
Sports.prototype = {
plus: function() {
this.count+= 1;
},
get: function() {
// setTimeout 밖에서의 this를 변수로 선언
let self = this;
setTimeout( () => {
// setTimeout 밖의 this와 비교
console.log(self === this);
this.plus();
console.log(this.count);
}, 1000 );
}
};

let newSports = new Sports();
newSports.get();

예제와 같이 화살표 함수로 작성하면 화살표 함수 블록에서 this가 Sports를 참조하는 것을 확인할 수 있습니다.


3.9 prototype


prototype에 화살표 함수를 연결하면 화살표 함수 블록에서 this가 인스턴스를 참조하지 못합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* [소스 arrow-71] */
let Sports = function(){
this.count = 20;
};
Sports.prototype = {
add: () => {
// prototype내 화살표 함수에서는 this가 window를 참조
this.count+= 1;
console.log(this);
console.log(this === window);
}
};
let newSports = new Sports();

newSports.add();
console.log(newSports.count);
// 여기서 값이 'NaN'으로 출력되는 이유는 undefined + 1의 계산이기 때문
console.log(window.count);

화살표 함수인 add()를 newSports.add()의 형태로 호출할 때 newSports의 프로퍼티 count를 참조하지 않고 window.count를 참조하게 됩니다.
prototype에 화살표 함수를 연결하면 this가 메서드를 호출하는 인스턴스 대신 window 오브젝트를 참조하게 되므로 화살표 함수가 아닌 function 키워드 함수를 prototype에 연결해서 사용해야 합니다.


요약


화살표 함수

  • 화살표 함수는 function 키워드보다 간단하게 사용할 수 있지만 모든 경우에 사용할 수 없으며 실행되는 환경이 고려되어야 한다.
  • 작성 방식은 함수의 형태에 따라 매우 다양하다
  • 오브젝트를 반환하려면 소괄호()안에 블록{}을 넣는 형태로 작성해야 한다.
  • new 연산자를 통한 인스턴스 생성이 불가능하다.
  • arguments 프로퍼티를 사용할 수 없다. (rest 파라미터로 대체할 수 있음)
  • function 키워드와 달리 자신의 this객체를 생성하지 않기 때문에 사용 상 주의가 필요하다
  • prototype에서 this가 인스턴스를 참조하지 못한다.