티스토리 뷰
화살표 함수(Arrow function)
화살표 함수 표현은 일반 함수 표현보다 간결하게 함수를 표현할 수 있습니다.
또한, this, arguments, super, new.target을 바인딩하지 않습니다.
화살표 함수는 익명 함수이기 때문에, 메소드가 아닌 함수에 사용하는 것이 적절합니다. 또한 익명 함수이기 때문에 생성자로 사용할 수 없습니다.
1. 문법
기본 문법
(param1, param2, …, paramN) => { statements }
(param1, param2, …, paramN) => expression
// 다음과 동일함: => { return expression; }
// 매개변수가 하나뿐인 경우 괄호는 선택사항:
(singleParam) => { statements }
singleParam => { statements }
// 매개변수가 없는 함수는 괄호가 필요:
() => { statements }
고급 문법
// 객체 리터럴 식을 반환하는 본문(body)을 괄호 속에 넣음:
params => ({foo: bar})
// 나머지 매개변수 및 기본 매개변수가 지원됨
(param1, param2, ...rest) => { statements }
(param1 = defaultValue1, param2, …, paramN = defaultValueN) => { statements }
// 매개변수 목록 내 구조분해도 지원됨
var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
f(); // 6
화살표 함수는 나머지 매개변수(Rest parameter) ([자바스크립트] ES6(ECMA Script 6) - 나머지 매개변수(Rest parameter) 참고)
기본 매개변수(Default parameter) ([자바스크립트] ES6(ECMA Script 6) - 기본 매개변수(Default parameter) 참고)
구조분해(Destructuring) ([자바스크립트] ES6(ECMA Script 6) - 구조분해 할당(Destructuring assignment) 참고)를 지원합니다.
2. 설명
짧아진 함수
var materials = [
"Hydrogen",
"Helium",
"Lithium",
"Beryllium"
];
var materialsLength1 = materials.map(function(material){
return material.length
});
var materialsLength2 = materials.map((material)=>{
return material.length
});
var materialsLength3 = materials.map(material=> material.length);
화살표 함수를 사용하면 함수를 정의 할 때, 코드랑을 줄일 수 있습니다.
this가 바인딩 되지 않음
화살표 함수의 등장 이전까지는 모든 새로운 함수를 정의하면 각각의 this가 존재했습니다.
function Person() {
// Person() 생성자는 `this`를 자신의 인스턴스로 정의.
console.log(this);
setTimeout(function growUp() {
// 비엄격 모드에서, growUp() 함수는 `this`를
// 전역 객체로 정의하고, 이는 Person() 생성자에
// 정의된 `this`와 다름.
console.log(this);
}, 1000);
}
var p = new Person();
this객체가 window로 바인딩 됨
setTimeout으로 호출된 growUp 함수의 this객체가 window로 바인딩되어 window를 출력하는 것을 확인 할 수 있습니다.
Person의 this객체와 growUp의 this객체는 서로 다른 객체입니다.
이러한 문제를 해결하기 위해 아래와 같이 코드를 작성할 수 있습니다.
function Person() {
console.log(this);
var that = this
setTimeout(function growUp() {
console.log(that);
}, 1000);
}
var p = new Person();
this를 변수에 저장하여 해결
또는 bind() 함수를 통해 this를 바인딩하여 해결 할 수도 있습니다.
function Person() {
console.log(this);
setTimeout((function growUp() {
console.log(this);
}).bind(this), 1000);
}
var p = new Person();
bind 함수를 사용하여 해결
화살표 함수는 자신의 this객체를 생성하지 않기 때문에 위와 같은 방법 없이도 this를 사용할 수 있습니다.
function Person() {
console.log(this);
setTimeout(() => { console.log(this) }, 1000);
}
var p = new Person();
화살표 함수는 this를 생성하지 않습니다.
또한 화살표 함수는 call, apply 함수로 this를 바인딩할 수 없습니다.
화살표 함수는 call, apply 함수로 this를 바인딩할 수 없습니다. call, apply로 전달된 this는 무시되고, 파라미터만 전달됩니다.
var f = v => {
console.log(v);
console.log(this);
};
f.call(true, 1);
f.apply(true, [2]);
call, apply 함수로 this를 바인딩할 수 없습니다.
arguments가 바인딩 되지 않음
화살표함수는 arguments를 바인딩하지 않습니다. arguments를 바인딩하지 않기 때문에 화살표 함수 내의 arguments는 scope안에 존재하는 arguments가 됩니다.
var arguments = 42;
var arr = () => arguments;
console.log(arr()); // 42
function foo() {
var f = (i) => arguments[0]+i; // foo 함수의 암시된 arguments 바인딩
return f(2);
}
console.log(foo(1)); // 3
arguments가 바인딩 되지 않음
arguments의 대안으로 나머지 매개변수(Rest parameter)를 사용할 수 있습니다.
function foo() {
var f = (...args) => args[0];
return f(2);
}
console.log(foo(1)); // 2
arguments의 대안으로 나머지 매개변수(Rest parameter)를 사용
화살표 함수를 메소드로 사용하기
메소드가 아닌 함수에 사용하는 것이 적절합니다. 라고 말씀드렸지만, 화살표 함수로 메소드를 만드는 것이 불가능하지는 않습니다.
var obj = {
i: 10,
b: () => console.log(this.i, this),
c: function() {
console.log( this.i, this)
}
}
obj.b();
obj.c();
화살표 함수를 메소드로 사용하기
화살표 함수로 구현된 메소드 b와 일반 함수로 구현된 메소드 c가 있습니다. 각각의 메소드에서 this를 출력해 본 결과,
b 메소드의 this는 window가 됩니다. 그 이유는 앞에서 말씀드렸던 것과 같이, 화살표 함수는 자신의 this객체를 바인딩(생성)하지 않기 때문에, window 객체가 됩니다. 반면에 c 메소드는 this객체는 바인딩되어 obj의 this객체가 됩니다.
화살표 함수를 메소드에 사용하지 않는 편이 좋지만, 사용하게 된다면 this에 유의해서 사용해야 합니다.
화살표 함수는 new가 되지 않음
var Foo = () => {};
var foo = new Foo(); // TypeError: Foo is not a constructor
화살표 함수는 new 가 되지 않음
화살표 함수는 프로토타입(prototype)을 가지지 않음
화살표 함수는 프로토타입을 가지지 않습니다. new가 되지 않기 때문에 당연한 이야기 일 수 있습니다.
var Foo = () => {};
console.log(Foo.prototype); // undefined
화살표 함수는 프로토타입(prototype)을 가지지 않음
3. 화살표 함수 사용시 유의사항
화살표 함수의 본문
화살표 함수의 본문(body)는 간결한 방법으로, 혹은 익숙한 블록({})으로 표현할 수 있습니다.
간결한 방법으로 본문을 작성할 경우 암시적으로 return값이 정해지지만, 블록({})으로 본문을 작성할 경우 return을 해주어야 합니다.
var func = x => x * x; // concise syntax, implied "return"
var func = (x, y) => { return x + y; }; // with block body, explicit "return" needed
리터럴 객체 반환
간격한 본문으로 화살표 함수를 작성하여 리터럴 객체를 반환 할 때, () 안에서 반환할 리터럴 객체를 정의해야 합니다.
var func = () => { foo: 1 };
console.log(func());
() 안에 리터럴 객체를 사용하지 않으면 반환값이 undefined
var func = () => ({ foo: 1 });
console.log(func());
() 안에서 반환할 리터럴 객체를 정의해야 합니다.
줄바꿈
화살표 함수를 정의할 때 줄바꿈 후 => 사용히 SyntaxError가 발생합니다. 줄바꿈 뒤에 => 키워드를 사용하면 안됩니다.
var func = ()
=> 1; // SyntaxError: expected expression, got '=>'
줄바꿈 뒤에 '=>' 시 SyntaxError
파싱 순서
화살표 함수의 =>는 연산자는 아니지만, 일반 함수와 비교했을 때 연산자 우선순위가 다르게 반응하는 특별한 룰을 가지고 있습니다.
let callback;
callback = callback || function() {}; // ok
callback = callback || () => {}; // SyntaxError: invalid arrow-function arguments
callback = callback || (() => {}); // ok
4. 예제
// empty 화살표 함수는 undefined를 반환
let empty = () => {};
(() => "foobar")() // "foobar" 반환
var simple = a => a > 15 ? 15 : a;
simple(16); // 15
simple(10); // 10
let max = (a, b) => a > b ? a : b;
// 쉬운 배열 필터링, 매핑, ...
var arr = [5, 6, 13, 0, 1, 18, 23];
var sum = arr.reduce((a, b) => a + b); // 66
var even = arr.filter(v => v % 2 == 0); // [6, 0, 18]
var double = arr.map(v => v * 2); // [10, 12, 26, 0, 2, 36, 46]
// 더 간결한 프로미스 체인
promise.then(a => {
// ...
}).then(b => {
// ...
});
'JavaScript' 카테고리의 다른 글
| [자바스크립트] 정규식(Regular Expressions) (10) | 2017.02.08 |
|---|---|
| [자바스크립트] ES6(ECMA Script 6) - for ... of 문 (0) | 2017.01.20 |
| [자바스크립트] ES6(ECMA Script 6) - 구조분해 할당(Destructuring assignment) (7) | 2017.01.18 |
| [자바스크립트] ES6(ECMA Script 6) - 기본 매개변수(Default parameter) (1) | 2017.01.17 |
| [자바스크립트] ES6(ECMA Script 6) - 나머지 매개변수(Rest parameter) (1) | 2017.01.16 |
