화살표 함수 표현(arrow function expression)은 function 표현에 비해 구문이 짧고 자신의 this, arguments, super 또는 new.target 을 바인딩 하지 않습니다. 화살표 함수는 항상 익명입니다. 이 함수 표현은 메소드 함수가 아닌 곳에 가장 적합합니다. 그래서 생성자로서 사용할 수 없습니다.
const tottenham = ['Son','Kane','Alli','Moura']; console.log(tottenham.map(name => name.length)) // Array [3, 4, 4, 5]
일부 함수 패턴에서는, 짧은 함수가 좋습니다. 비교해보겠습니다.
const tottenham = [ 'Son', 'Kane', 'Alli', 'Moura' ]; /* 일반적인 함수 표현 */ tottenham.map(function(name){ return name.length; }); // [3, 4, 4, 5] /* 화살표 함수 표현 */ tottenham.map((name) => { return name.length; }); // [3, 4, 4, 5] /* 파라미터가 하나만 있을 때는 주변 괄호를 생략 */ tottenham.map(name => { return name.length; }); // [3, 4, 4, 5] /* 화살표 함수의 유일한 문장이 'return' 일 때 'return' 과 중괄호 ({}) 를 생략 */ tottenham.map(name => name.length); // [3, 4, 4, 5] /* 위의 예시의 경우 length 속성만 필요하므로 destructuring 매개변수를 사용 */ tottenham.map(({ length: lengthName }) => lengthName); // [3, 4, 4, 5] // 'length' 는 우리가 얻고자 하는 속성에 해당하는 반면, // lengthName 은 변경 가능한 변수의 이름일 뿐이므로 // 원하는 유효한 변수명으로 변경할 수 있다. /* destructuring 파라미터 할당 */ tottenham.map(({ length }) => length); // [3, 4, 4, 5] // 이 예에서 정의한 객체내의 'length' 에 값을 지정하지 않은 점에 주목하세요. // 대신, 'length' 변수의 리터럴 이름은 우리가 해당 객체에서 꺼내오고 싶은 속성이름 자체로 사용됩니다.
화살표 함수가 나오기 전까지는, 모든 새로운 함수는, 어떻게 그 함수가 호출되는지에 따라 자신의 this 값을 정의했습니다. 이는 객체 지향 스타일로 프로그래밍할 때 별로 좋지 않습니다.
function Person() { // Person() 생성자는 'this' 를 자신의 인스턴스로 정의 this.age = 0; setInterval(function growUp() { // 비엄격 모드에서, growUp() 함수는 'this' 를 전역 객체로 정의하고, 이는 Person() 생성자에 정의된 'this' 와 다름 this.age++; }, 1000); } let person = new Person();
ECMAScript 3/5 에서는, 이 문제를 this 값을 패쇄될 수 있는 (비전역) 변수에 할당하여 해결했습니다.
function Person() { var that = this; that.age = 0; setInterval(function growUp() { // 콜백은 `that` 변수를 참조하고 이것은 값이 기대한 객체이다. that.age++; }, 1000); } let person = new Person();
이렇게 하는 대신에, 바인딩한 함수는 적절한 this 값이 growUp() 함수에 전달될 수 있도록 생성될 수 있습니다. 화살표 함수는 자신의 this 가 없습니다. 대신에 화살표 함수를 둘러싸는 렉시컬 범위(lexical scope)의 this 가 사용됩니다. 화살표 함수는 일반 변수 조회 규칙(normal variable lookup rules)을 따릅니다. 때문에 현재 범위에서 존재하지 않는 this 를 찾을 때, 화살표 함수는 바로 바깥 범위에서 this 를 찾는 것으로 검색을 끝내게 됩니다. 따라서 다음 코드에서 setInterval 에 전달 된 함수 내부의 this 는 setInterval 을 포함한 function 의 this 와 동일한 값을 갖습니다.
function Person(){ this.age = 0; setInterval(() => { this.age++; // this 는 Person 객체를 참조 }, 1000); } let person = new Person();
화살표 함수에서는 this 가 바인딩되지 않았기 때문에, call() 또는 apply() 메서드는 인자만 전달할 수 있습니다. this 는 무시됩니다.
let adder = { base: 1, add: function(a){ let f = v => v + this.base; return f(a); }, addThruCall: function(a) { let f = v => v + this.base; let b = { base: 2 }; return f.call(b, a); // 화살표 함수에서는 this 바인딩x }; } console.log(adder.add(1)); // 2 console.log(adder.addThruCall(1)); // 2
화살표 함수는 arguments 객체를 바인드 하지 않습니다. 때문에, arguments 는 그저 둘러싸는 범위(scope)내 이름에 대한 참조입니다.
let arguments = [1, 2, 3]; let arr = () => arguments[0]; arr() // 1 function foo(n) { let f = () => arguments[0] + n; return f(); } foo(1) // 2
화살표 함수는 자신의 arguments 객체가 없지만, 대부분의 경우에 나머지 매개변수가 좋은 대안입니다.
function foo(n){ let f = (...args) => args[0] + n; return f(2); } foo(1); // 3
이야기 했듯이, 화살표 함수 표현은 메소드 함수가 아닌 형태로 사용 할 수 있습니다.
메소드로 사용하려고 하면 아래와 같은 일이 발생합니다.'use strict'; let obj = { // does not create a new scope i: 10, b: () => console.log(this.i, this), c: function () { console.log(this.i, this); } } obj.b(); // undefined, window 객체 obj.c() // 10, obj
화살표 함수는 생성자로서 사용될 수 없으며 new와 함께 사용하면 오류가 발생합니다.
var Foo = () => {}; var foo = new Foo(); // TypeError: Foo is not a constructor
화살표 함수는 prototype 속성이 없습니다.
var Foo = () => {}; console.log(Foo.prototype); // undefined
var func = (a, b, c) =>
1;
var func = (a, b, c) => (
1
);
var func = (a, b, c) => {
return 1
};
var func = (
a,
b,
c
) => 1;
// SyntaxError가 발생하지 않습니다.