티스토리 뷰
화살표 함수(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 |