JS Study : ES6 - 1주차(Arrow function)

👊0👊·2020년 1월 11일
0

es6 스터디

목록 보기
1/8

화살표 함수(Arrow function)

가독성 좋은 익명함수

화살표함수는 정말 편리한 익명함수 선언 방식이다. 함수형 패러다임이 인기를 끌면서 익명함수를 작성할일이 많은데, 화살표함수은 익명함수를 엄청 간단하게 선언한다.

const f1 = function(a,b,c) { return a+b+c; }

const f2 = (a,b,c) => a+b+c;

const f3 = [1,2,3,4,5].map(function(i) { return i*i; })

const f4 = [1,2,3,4,5].map(i => i*i);

function, return 키워드가 제거된 것을 볼 수 있다.
특히 ES6의 새로생긴 Array의 메서드(map,filter,reduce)를 보기 좋게 작성할 수 있다.
하지만 화살표함수가 이런 가독성만 차이를 가지고 있지 않다.

자신의 this, arguments, super 또는 new.target을 바인딩 하지 않는다.
화살표 함수는 항상 익명이다. 그래서 메서드와 생성자로 사용하기에 적합하지 못하다.

차이점

  • this
  • arguments
  • super
  • new.target

앞에서 말한 것처럼 화살표함수은 익명함수이다.

차이점 ES5

arrow 이해하기 위해 babel이 어떻게 transpiling하는지 알아보자.

const나 map은 넘어가자. 또한 옵션을 주어서 bind()를 사용하여 transpiling할 수도 있다.

var a = () => {};
var a = (b) => b;

const double = [1,2,3].map((num) => num * 2);
console.log(double); // [2,4,6]

var bob = {
  _name: "Bob",
  _friends: ["Sally", "Tom"],
  printFriends() {
    this._friends.forEach(f =>
      console.log(this._name + " knows " + f));
  }
};
console.log(bob.printFriends());
var a = function () {};
var a = function (b) {
  return b;
};

const double = [1, 2, 3].map(function (num) {
  return num * 2;
});
console.log(double); // [2,4,6]

var bob = {
  _name: "Bob",
  _friends: ["Sally", "Tom"],
  printFriends() {
    var _this = this;

    this._friends.forEach(function (f) {
      return console.log(_this._name + " knows " + f);
    });
  }
};
console.log(bob.printFriends());

this 정적 vs 동적

변수에 익명함수로 작성한 화살표함수는 단순하게 functionreturn키워드를 붙혀서 우리가 아는 익명함수로 변환됐다.

그럼 bob 메서드인 printFriends안에 사용된 forEach에 화살표함수가 사용되었다.
우리는 전통적인 함수에서 this는 호출방식에 의해서 동적으로 결정된다고 배웠다.
하지만 화살표 함수는 정적으로 결정된다. 화살표 함수의 this 언제나 상위 스코프의 this를 가리킨다. 이를 Lexical this라 한다.

ES5 코드를 보면 printFirend에 바로 var _this = this;로 상위 스코프의 this를 메소드 내부에 할당한 것을 볼 수 있다.
그리고 화살표 함수에서 사용한 this_this로 치환되었다.

전통적인 함수의 this는 동적으로 결정되지만, 화살표 함수의 this는 lexcial하게 결정된다.

arrow function의 call, apply, bind

화살표 함수의 this는 렉시컬하게 결정된다 했다. 그럼 함수호출과 관련된 메서드 call, apply, bind는 사용할 수 있을까? 당연하게도 이 메서드의 this는 무시되고 인자들만 받는다.

화살표 함수는 렉시컬한 익명함수를 선언하기 위해 만들어졌다는 것을 다시 기억해보자. 굳이 bind, call, apply로 this를 결정하는 것은 불필요하다.

var adder = {
  base : 1,
    
  add : function(a) {
    var f = v => v + this.base;
    return f(a);
  },

  addThruCall: function(a) {
    var f = v => v + this.base;
    var b = {
      base : 2
    };

    return f.call(b, a);
  }
};

console.log(adder.add(1));         // 이는 2가 콘솔에 출력될 것임
console.log(adder.addThruCall(1)); // 이도 2가 콘솔에 출력될 것임

그외 arguments, super, new.target

arguemts

익명함수에는 arguments가 없다. 검색을 해도 정확한 이유를 모르겠다.
몇 가지 이유는 생각해보았다.
1. 함수의 가독성을 위해서
function sumAll()의 선언보다는 sumAll(...args)이 좀 더 가독성이 좋다.
2. 성능상의 이유
아주 약간 빠른 것 같긴한데 정확히 모르겠다.
3. arguemtns는 뭔가 구려서
* 명시적으로 없는 인자라는게 뭔가 구리다.

super

super 키워드는 부모 오브젝트의 함수를 호출할 때 사용된다. 화살표함수는 클래스를 선언할일 없지 않나. 필요없다.

new.target

new.target 속성(property)은 함수 또는 생성자가 new 연산자를 사용하여 호출됐는지를 감지할 수 있다.
화살표 함수는 익명함수로 사용되어야 한다. new로 생성하면 안된다.

function Foo() {
  if (!new.target) throw 'Foo() must be called with new';
}

하면안되는 것들

  • 메소드로 사용되는 화살표 함수
  • new 연산자 사용
  • prototype 속성 사용
  • yield 키워드 사용

렉시컬적인 익명함수를 떠올리면 왜 위에 언급된 사용법이 안되는지 생각할 수 있다.

참고자료

profile
ㅎㅎ

0개의 댓글