본문 바로가기

JavaScript

20210709 JavaSciprt DeepDive 08 : ES6 메서드(축약표현), 화살표 함수, Rest 파라미터, 매개변수 기본값

JavaScript Deep Dive 08



용어 및 중요사항 정리


ES6 함수의 추가 기능


  • 자바스크립트에서 ES6 이전 함수는 다양한 방식으로 호출이 가능함 -> 함수의 구분이 없음, 대부분이 프로토타입 객체를 생성함 -> 실수 유발, 성능 저하
    • 일반 함수 호출
    • 생성자 함수 호출
    • 메서드로서 호출
    • callble(호출할 수 있는 함수 객체) 이면서 contructor(인스턴스를 생성할 수 있는 함수 객체) 임

함수 구분 constructor prototype super arguments
일반함수
(함수 선언문, 표현식)
O O X O
메서드 X X O O
화살표 함수 X X X X

ES6 메서드 (메서드 축약 표현)


  • 메서드 :
    • 과거 : 객체에 바인딩된 함수를 일컫는 의미
    • ES6 : 메서드 축약 표현으로 정의된 함수만 의미
      • non-consturctor로 인스턴스 생성 X -> 생성자 함수로서 호출 X
      • prototype 프로퍼티 X, 프로토타입 생성 X
    • 표준 빌트인 객체가 제공하는 프로토타입 메서드, 정적 메서드는 non-contructor 임 (메서드니까)
    • ES6 메서드는 자신을 바인딩한 객체를 가리키는 내부 슬롯 [[HomeObject]]를 갖음 -> super 키워드 사용 가능
      • 객체 리터럴 방식의 객체의 __proto__ 프로퍼티에 부모를 할당하여 상속 구현이 가능함
    • 메서드 정의시 프로퍼티에 익명 함수 표현식을 할당하는 방식은 사용하지 말자
const obj = {
  x: 1,
  foo() {
    return this.x;
  }, // ES6 메서드
  bar: function () {
    return this.x;
  }, // 일반 함수
};
console.log(obj.foo()); // 1 (ES6 메서드)
console.log(obj.bar()); // 1 (일반 함수)
new obj.foo(); // Type Error : not a constructor (ES6 메서드)
new obj.bar(); // bar{} (일반 함수)
obj.foo.hasOwnProperty("prototype"); // false (ES6 메서드)
obj.bar.hasOwnProperty("prototype"); // true (일반 함수)

화살표 함수


  • 화살표 함수:
    • 함수 선언문으로 정의할 수 없고 함수 표현식으로 정의함 (호출 방식은 기존 함수와 동일)
    • 매개변수 :
      • 매개 변수가 여러 개인 경우 소괄호 ()안에 매개변수 선언
      • 1개인 경우 소괄호 생략 가능, 0개인 경우 소괄호 생략 불가
      • 중복된 매개변수 이름 선언 X, Duplicate prameter name X (일반 함수는 가능함)
    • 함수 몸체 :
      • 표현식인 문 하나로 된 경우만 중괄호 생략 가능 (해당 표현식인 문은 return 값으로 인식)
        • 여러개의 문으로 구성되면 중괄호 생략 불가
      • 객체 리터럴 반환시 ()소괄호로 묶어주어야 함
        • 객체 리터럴의 중괄호 보다, 함수 몸체를 의미하는 중괄호가 우선되어 인식
    • 즉시 실행 함수 사용 가능
    • 화살표 함수는 일급객체임 -> 고차함수(HOF)에 인수로 전달 가능
      • 콜백함수 정의시 유용
    • 인스턴스 생성 불가한 non-constructor 임 -> 생성자 함수로서 호출 X, 프로토타입 생성 X
    • 함수 자체 this, arguments, super, new.target 바인딩 X -> 상위 스코프 기준으로 바인딩 O
    • 화살표 함수로 기존의 메서드를 만들지 말자, 메서드는 항상 ES6 메서드 축약만 사용하자

  • 화살표 함수의 this
  • 콜백함수 내부의 this 문제
    • 콜백함수가 함수 표현식으로 작성된 경우, 콜백함수는 일반 함수로 호출 됨
      • 일반 함수로 호출되면 this는 전역객체를 가리킴
      • strict mode + 일반함수 호출 -> this는 undefined를 가리킴
    • 콜백함수 외부 this와 콜백함수 내부의 this가 차이가 생김
    • 콜백 함수 내/외부 this를 일치 시키는 방법
      • 방법01: 외부에서 this를 변수에 할당시켜 받아서, 내부에서 변수을 참조하여 사용
      • 방법02: 두번째 인수를 콜백함수 내부의 this로 사용할 객체를 전달하는 기능이 있는 함수를 사용
        • ex) Array.prototype.map(callback, this)
      • 방법03: Function.prototype.bind 메서드 활용하여 콜백함수에 bind를 붙여 외부 this를 바인딩
        • bind() : 내부 this에 바인딩 될 값을 지정함 (.bind(this) -> 외부 this를 바인딩)
      • 방법04: 화살표 함수를 사용하기
        • 화살표 함수는 자체 this 바인딩이 없어 this 사용시 상위 스코프의 this를 그대로 참조하는 특성을 가졌음
        • lexical this : 화살표 함수의 this의 기능을 가진 this를 말함
          • 렉시컬 스코프처럼, 화살표 함수가 정의된 위치에 의해 this가 결정되는 것
          • 화살표 함수가 중첩되어 있는 경우 -> 화살표 함수가 아닌 가장 가까운 함수의 this를 참조
        • 화살표 함수의 경우 this 바인딩이 없기 때문에 call, apply, bind 메서드를 사용해도 this 지정이 불가함
// 화살표 함수의 this 바인딩
// call을 통해서 외부 함수의 this가 정해짐 -> 화살표 함수 this 검색을 통한 this 참조가 일어남
(function () {
  const foo = () => console.log(this);
  foo();
}.call({ a: 1 })); // { a: 1 }

// 화살표 함수 중첩인 경우 this 검색
(function () {
  const bar = () = () => console.log(this);
  bar();
}.call({ a: 1 })); // { a: 1 }

// 화살표 함수에서 call, apply, bind 메서드 무시 (this가 없으므로)
window.x = 1
const normal = function() {return this.x}
const arrow = () => this.x

console.log(normal.call({x: 10})) // 10
console.log(arrow.call({x: 10})) // 1

  • 프로토타입 객체의 프로퍼티에 함수를 넣는 경우
    • 화살표 함수로 할당하는 경우 화살표 함수의 this는 window를 가리킴
    • 함수 표현식을 할당하는 경우 this는 호출된 인스턴스를 가리킴
    • ES6 메서드를 사용하는 경우 프로토타입 객체에 새로운 객체를 할당하는 방식으로 ES6메서드를 사용하고, constructor 프로퍼티를 만들어서 생성자 함수간의 연결을 해줘야 함

  • 클래스 필드에 화살표 함수 할당

    • 클래스 필드에 this를 포함하는 화살표 함수를 할당하는 경우 -> 예외적으로 this는 인스턴스를 가리킴
      • 이 상황에서 화살표 함수의 상위 스코프는 클래스 외부임
  • 클래스의 constructor 메서드에 화살표 함수 할당

    • 클래스 필드와 마찬가지로 this가 인스턴스를 가리킴

  • 화살표 함수의 super

    • 화살표 함수는 함수 자체 super 바인딩이 없어 화살표 함수 자신 자체의 super를 사용할 수 없음
    • 화살표 함수에서 super 참조시 this와 마찬가지로 상위 스코프 contructor의 super참조
    • super은 [[HomeObject]]를 갖는 ES6 메서드 내에서만 사용할수 있는 키워드임
    • 클래스 필드에 super를 참조하는 화살표 함수를 할당하면, constructor 내부의 super를 바인딩을 참조함
      • 클래스 필드를 사용하면, constructor를 생략해도 암묵적으로 constructor가 생성되므로
  • 화살표 함수의 arguments

    • 화살표 함수는 arguments 바인딩이 없어서 화살표 함수 자체의 arguments 객체를 사용할 수 없음
    • 상위 스코프의 arguments를 참조함
      • arguments가 작용되더라도 상위 스코프 arguments 객체인 것임

Rest 파라미터


  • Rest 파라미터 : 함수에 전달된 인수들의 목록을 배열로 전달 받음
    • ...매개변수의 형태로 매개변수를 작성함
    • Rest 파라미터는 반드시 마지막 파라미터이어야 함
    • Rest 파라미터는 단 하나만 선언 가능함
    • 일반 매개 변수와 rest 파라미터를 함께 사용할 수 있음
      • 인수는 매개변수, rest 파라미터 순차적으로 할당 됨
      • 매개변수는 매개변수 대로 인수가 들어가고, rest 파라미터 순서 부터는 rest 파라미터에 할당됨 (rest 파라미터에는 매개변수의 인수는 제외 됨)
    • Rest 파라미터는 함수객체의 length 프로퍼티에 포함되지 않음
      • length 프로퍼티 : 함수정의시 선언한 매개변수의 개수

  • Rest 파라미터 vs arguments 객체
비교 Rest 파라미터 arguments 객체
개념 인수 정보 O 인수 정보 O
표현 ...매개변수 자동 생성됨
반환 배열 객체 유사 배열 객체
배열 메서드 직접 사용 가능 call, apply로 간접적으로
사용해서 변환 필요
함수 내부
지역변수 사용
O (매개변수) O(arguments)
(ES6)단축 메서드 O O
화살표 함수 O X
기본값 지정 기능 X O (영향 안받기 때문)
  • 매개변수 기본값
    • JS 엔진은 매개변수와 인수의 개수를 체크 X -> error 발생 X
    • 인수가 전달되지 않은 매개변수 : undefined
      • 기존 논리 연산자를 통한 인수 체크 및 기본값 설정 방식 (or 연산자)
    • ES6의 인수체크 및 초기화
      • 매개변수에 할당 연산자를 통해서 값을 할당하는 표현으로 사용함
      • 인수전달 안한 경우, undefined 전달한 경우에만 기본값이 작용됨
    • rest 파라미터는 ES6 방식 기본값 설정 불가
    • arguments객체 영향 받지 않음 (기본값 사용 가능)
function sum1(x, y) {
  x = x || 0;
  y = y || 0;
  return x + y;
}
console.log(sum1(1, 2)); // 3
console.log(sum1(1)); // 1

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