티스토리 뷰


ES6


화살표 함수(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로 바인딩 됨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를 변수에 저장하여 해결this를 변수에 저장하여 해결


또는 bind() 함수를 통해 this를 바인딩하여 해결 할 수도 있습니다.

function Person() {
    console.log(this);

    setTimeout((function growUp() {
        console.log(this);
    }).bind(this), 1000);
}

var p = new Person();

bind 함수를 사용하여 해결bind 함수를 사용하여 해결


화살표 함수는 자신의 this객체를 생성하지 않기 때문에 위와 같은 방법 없이도 this를 사용할 수 있습니다.

function Person() {
    console.log(this);

    setTimeout(() => { console.log(this) }, 1000);
}

var p = new Person();

화살표 함수는 this를 생성하지 않습니다.화살표 함수는 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를 바인딩할 수 없습니다.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가 바인딩 되지 않음


arguments의 대안으로 나머지 매개변수(Rest parameter)를 사용할 수 있습니다.

function foo() { 
    var f = (...args) => args[0]; 
    return f(2); 
}
console.log(foo(1)); // 2

arguments의 대안으로 나머지 매개변수(Rest parameter)를 사용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 가 되지 않음화살표 함수는 new 가 되지 않음


화살표 함수는 프로토타입(prototype)을 가지지 않음

화살표 함수는 프로토타입을 가지지 않습니다. new가 되지 않기 때문에 당연한 이야기 일 수 있습니다.

var Foo = () => {};
console.log(Foo.prototype); // undefined

화살표 함수는 프로토타입(prototype)을 가지지 않음화살표 함수는 프로토타입(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() 안에 리터럴 객체를 사용하지 않으면 반환값이 undefined


var func = () => ({ foo: 1 });
console.log(func());

() 안에서 반환할 리터럴 객체를 정의해야 합니다.() 안에서 반환할 리터럴 객체를 정의해야 합니다.


줄바꿈

화살표 함수를 정의할 때 줄바꿈 후 => 사용히 SyntaxError가 발생합니다. 줄바꿈 뒤에 => 키워드를 사용하면 안됩니다.

var func = ()
           => 1; // SyntaxError: expected expression, got '=>'

줄바꿈 뒤에 '=>' 시 SyntaxError줄바꿈 뒤에 '=>' 시 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 => {
   // ...
});



댓글
공지사항
최근에 올라온 글