26장. ES6 함수의 추가 기능

유준상·2022년 2월 23일
1
post-thumbnail
  • 서론

     최근 컴공선배에서 주관하는 부트캠프에 참여중인데, 리액트를 처음으로 접하면서 이것저것 시도해보고 있다. 리액트를 진행하면서 느끼는 점은 나의 자바스크립트 실력이 굉장히 허접하다는 것이다.
     리액트에서 특히 많이 쓰는 화살표 함수나 배열같이 특히 많이 사용하는 문법들이 있는데, 프로젝트를 진행하면서 자주 쓰는 문법들을 정리해야 할 필요성을 크게 느꼈다.

  • 함수의 구분

    1) 일반적인 함수로 호출
    2) new 연산자와 함께 생성자 함수로 호출
    3) 객체에 바인딩되어 메서드로서 호출

    var foo = function () {
       return 1;
    };
    // 일반적인 함수로 호출
    foo(); // 1
    // 생성자 함수로 호출
    new foo(); // foo {}
    // 메서드로서 호출
    var obj = { foo: foo };
    obj.foo(); // 1

    ES6 이전에는 동일한 함수가 일반, 생성자 함수, 메서드로 모두 호출될 수 있다.
    --> 이는 편리해 보이지만 실수를 유발시킬 수 있으며, 성능적으로 손해이다!!
    이를 방지하기 위해 ES6에서는 non-constructor 인 화살표 함수의 개념이 생겼다.

  • 메서드

    ES6에서의 메서드는 메서드 축약 표현으로 정의된 함수만을 의미

    const obj = {
       x: 1,
       // foo 메서드
       foo() { return this.x; },
       // bar에 바인딩된 함수는 메서드가 아닌 일반 함수이다.
       bar: function() { return this.x; }
    };
    console.log(obj.foo()); // 1
    console.log(obj.var()); // 1

    1) ES6에서의 메서드는 non-constructor 이므로 인스턴스를 생성할 수 없다.
    --> 프로토타입 프로퍼티 x, 프로토타입 생성 x
    프로토타입, 정적 메서드는 모두 non-constructor 이다.
    2) ES6에서의 메서드는 자신을 바인딩한 객체를 가리키는 내부 슬롯 [[HomeObject]]를 가진다. --> super 키워드 사용이 가능하다.
    3) ES6 메서드가 아닌 함수는 super 키워드 사용이 불가능하다.
    ES6 메서드는 본연의 기능 (super) 을 추가하고, 의미적으로 맞지 않는 기능 (constructor) 을 제거하였다.
    --> 객체 내부에서 메서드를 정의할 때 메서드 축약 표현을 사용하자!

  • 화살표 함수

    1) 표현 및 내부 동작이 간략하다.
    2) 콜백 함수 내부에서 this가 전역 객체를 가리키는 문제 해결이 가능하다.

    1. 화살표 함수 정의

    함수 선언문이 아닌 함수 표현식으로 정의

    const multiply = (x,y) => x * y;
    multiply(2,3); // 6

    매개변수가 여러개인 경우 소괄호 안에 선언하고, 1개인 경우에는 소괄호 생략이 가능하다. 매개변수가 없는 경우 소괄호 생략이 불가능하다.

    const arrow = (x,y) => {...};
    const arrow2 = x => {...};
    const arrow3 = () => {...};

    함수 몸체가 하나의 문으로 구성된다면 중괄호 생략이 가능하다. 문이 표현식으로 평가될 수 있는 문이라면 return 키워드 없이 암묵적으로 반환한다.

    const power = x => x ** 2;
    power(2); // 4
    // 위와 동일하다.
    const power = x => { return x ** 2; };

    문이 표현식이 아닌 문이라면 중괄호를 생략했을 때 에러가 발생한다.
    객체 리터럴을 반환하는 경우에는 소괄호로 감싸준다.
    화살표 함수는 콜백 함수로서 정의할 때 매우 유용하다.

    2. 화살표 함수와 일반 함수의 차이

    1) 화살표 함수는 인스턴스를 생성할 수 없는 non-constructor 이다.
    2) 따라서, prototype 프로퍼티가 없고, 프로토타입도 생성하지 않는다.
    3) 중독된 매개변수 이름을 선언할 수 없다.
    4) 화살표 함수에서 this, arguments, super, new.target을 참조하면 스코프 체인을 통해 상위 스코프를 참조한다.

    3. this

    화살표 함수는 다른 함수의 인수로 전달되어 콜백 함수로 사용되는 경우가 많다.
    1) 일반함수

    class Prefixer {
      constructor(prefix) {
          this.prefix = prefix;
      }
      add(arr) {
          return arr.map(function (item) {
              return this.prefix + item;
          });
      }
    }

    콜백함수 내부의 함수가 일반 함수로서 호출한다. --> this는 전역 객체를 가리킴
    strict mode가 적용되어 this에 undefined가 바인딩
    2) 화살표 함수

    class Prefixer {
      constructor(prefix) {
          this.prefix = prefix;
      }
      add(arr) {
          return arr.map(item => this.prefix + item);
      }
    }

    화살표 함수는 함수 자체의 this 바인딩을 갖지 않는다. 따라서, 체인 스코프를 따라 상위 스코프의 this를 그대로 참조한다. --> 렉시컬 this
    call, apply, bind 메서드를 통해 함수 내부의 this 교체가 불가능하다.
    메서드를 화살표 함수로 정의하는 것은 피해야 한다.
    --> this가 메서드를 호출한 객체가 아닌 전역을 가리킨다!!!
    --> 메서드는 ES6의 메서드 축약 표현을 사용하자.
    --> 그러나 프로퍼티를 동적으로 추가하기 위해서는 일반 함수를 사용한다.

    4. super

    화살표 함수는 함수 자체의 super 바인딩을 갖지 않는다.
    this와 마찬가지로 상위 스코프의 super를 참조한다.

    class Base {
      constructor(name) {
          this.name = name;
      }
      sayHi() {
          return `Hi! ${this.name}`;
      }
    }
    class Derived extends Base {
      sayHi = () => `${super.sayHi()} how are you doing?`;
    }
    const derived = new Derived('Lee');
    console.log(derived.sayHi()); // Hi! how are you doing?

    5. arguments

    화살표 함수는 함수 자체의 arguments 바인딩을 갖지 않는다.
    this, super와 마찬가지로 상위 스코프의 arguments를 참조한다.
    --> 화살표 함수에서는 Rest 파라미터를 사용한다.

  • Rest 파라미터

    --> 함수에 전달된 인수들의 목록을 배열로 전달받는다.

    function foo(...rest) {
       console.log(rest); // [1,2,3,4,5]
    }
    foo(1,2,3,4,5);

    일반 매개변수와 Rest 파라미터는 함께 사용이 가능하다

    function foo(param, ...rest) {
     console.log(param); // 1
     console.log(rest); // [2,3,4,5]
    }
    foo(1,2,3,4,5);

    단, Rest 파라미터가 가장 마지막 파라미터여야 한다.
    Rest 파라미터는 단 1개만 선언이 가능하다.
    foo 파라미터는 매개변수 개수를 나타내는 length 프로퍼티에 영향 x

    Rest 파라미터와 arguments 객체

    arguments 객체는 배열이 아닌 유사 배열이므로 배열 메서드를 사용하려면 call, apply 메서드로 객체 변환이 필요하다.
    --> Rest 파라미터가 이러한 번거로움을 해결해준다. (배열로 직접 전달받음)

  • 매개변수 기본값

    --> 매개변수의 개수만큼 인수를 전달하는 것이 좋지만, 그렇지 않아도 에러가 발생하지 않는다. 전달되지 않은 인수는 undefined 이다.
    --> OR 연산자를 통하여 기본값을 할당하여 방어할 수 있다.

    function sum(x,y) {
       x = x || 0;
       y = y || 0;
       return x + y;
    }
    console.log(sum(1,2)); // 3
    console.log(sum(1)); // 1 y=0

    ES6에서는 매개변수 기본값이 도입되었다.

    function sum(x = 0, y = 0) {
       return x + y;
    }
    console.log(sum(1)); // 1

    이는 매개변수에 인수를 전달하지 않는 경우와 undefined을 전달한 경우만 가능하다.
    Rest 파라미터는 기본값 설정이 불가능하다.
    매개변수 기본값은 length 프로퍼티에 영향을 미치지 않는다.

profile
웹사이트 개발과 신발을 좋아하는 학생입니다.

0개의 댓글

관련 채용 정보