JS Deep Dive | 2021.12.23

invidia·2021년 12월 24일
0

TIL

목록 보기
13/29

25. 클래스

정리

  • 생성자 함수와의 차이점
    1. new 연산자 없이 호출시 에러 발생
    2. 상속을 위한 extend, super 키워드 지원
    3. 호이스팅가 없는 것처럼 동작 (TDZ가 존재)
    4. 클래스 내에 strict mode 암묵적 지정 (해제 불가)
    5. 모든 메서드가 열거 불가
  • 클래스 정의
    • Ex) class Person {} 로 선언
    • 표현식으로도 정의 가능 const Person = class {}
      • 일급 객체임을 의미
  • 클래스 호이스팅
    • constructor()이 런타임 이전에 평가되어 프로토타입을 생성한다.
    • 클래스 정의 이전에 참조 불가능하다.
      • let, const 처럼 TDZ에 빠진다.

메서드

  • 인스턴스의 __proto__ : class.prototype
  • class의 prototype : constructor
    • class의 __proto__ : Function.prototype
  • 인스턴스를 둘러봐도 constructor()은 보이지 않는다.
    • 메서드로 해석 X
    • 클래스 평가될 때, 생성되는 함수 객체의 코드일부가 된다.

constructor

  • 프로퍼티 초기화 위해서 필요
  • 생략 가능 (빈 객체 생성)
  • 암묵적으로 this 반환 (원시값 반환시 무시하고 this 반환)
  • constructor(name = "person") 처럼 기본값 부여 가능

프로토타입 메서드

  • 기본적인 메서드 = 프로토타입 메서드

    • 클래스의 sayHi() === 생성자 함수의 Person.prototype.sayHi = function()
  • me -> Person.prototype의 -> Object.prototype

  • Person.prototype의 constructor : Person class

정적 메서드

  • 인스턴트 생성 없이도 호출할 수 있는 메서드
  • 클래스의 static sayHi() === 생성자 함수의 Person.sayHi()
  • 클래스에 바인딩된다.
  • 프로토타입에는 존재치않아, 인스턴스는 참조 불가능하다.

프로토타입 메서드와 정적 메서드 차이

  • 프로토타입 메서드는: this를 사용하는 경우
    • Ex) 인스턴스 값을 이용하는 경우
  • 정적 메서드는: this를 사용치 않는 경우
    • Ex) 유틸리티 함수

메서드 특징

  • 축약 표현 사용
  • 암묵적 strict mode
  • 열거 불가
    • [[Enumerable]] === false
  • new 연산자로 호출 불가
    • 축약표현이라 [[Construct]] 존재 X

인스턴스 생성 과정

  1. 인스턴스 생성 및 this 바인딩
    1. new 연산자로 호출 시 빈 객체(예비 인스턴스)가 생성
    2. 인스턴스에 프로토타입으로 class prototype을 지정
    3. constructor() 내부의 this를 인스턴스에 바인딩
  2. 인스턴스 초기화
  • constructor 내부 코드 실행되어 값의 초기화
  1. 완성된 인스턴스의 this 반환

프로퍼티

  • 인스턴스 프로퍼티 (일반적)
    • Always Public
  • 접근자 프로퍼티 (get, set)
    • 호출 X, 참조 & 할당시 내부적으로 호출

클래스 필드 정의 제안

  • JAVA, C# 처럼 클래스 몸체에 필드(변수)를 사용할 수 있도록 하는 것

  • 몸체에서 정의가능

  • 내부에서 참조시 반드시 this를 사용

  • 정의시 프로토타입이 아니라 인스턴스에 할당되어 권장 X

    • sayHi() : 프로토타입에 할당
    • sayHi = function() {...} : 인스턴스에 할당 (클래스 필드)

private 필드 정의 제안

  • 외부에서는 참조 불가 (접근자 프로퍼티 통해 간접 접근 가능)
  • Ex) #age

static 필드 정의 제안

  • 정적 필드 정의
  • Ex) static age = 22;

상속에 의한 클래스 확장

  • 프로토타입 기반의 상속상속에 의한 클래스 확장은 다르다.

    • 생성자 함수의 프로토타입 기반 상속은 상위 객체의 요소 참조가 핵심이다.
    • 클래스의 상속에 의한 확장은 상위 객체 요소 참조도 가능하지만, 프로퍼티와 메서드를 확장할 수 있는 문법이 제공된다.
    • 생성자 함수는 상속을 통해 새로운 인스턴스를 생성하지만, 클래스는 상속을 통해 새로운 클래스를 생성한다.

extends

  • 클래스의 prototype을 상속받는다.
    • constructor, 프로토타입 메서드를 상속한다.
  • 클래스 자체를 상속받는다.
    • 정적 메서드를 상속한다.
  • 클래스 뿐만이 아니라 생성자 함수도 상속받을 수 있다.
    • [[Construct]] 내부 메서드를 소유한 함수 객체로 평가가능한 표현식이면 전부 가능하다.
      • 조건문을 이용할 수도 있다.

super

  • 수퍼클래스의 constructor()를 호출

    • 서브클래스에서는 암묵적으로 constructor(...args) {super(...args)}가 정의된다.
    • constructor(a,b,c) {super(a,b); this.c = c;} 처럼 수퍼클래스와 서브 클래스가 협력하여 인스턴스를 생성할 수도 있다.
    • 주의 사항
      1. 서브클래스는 constructor()을 생략하지 않을 경우 그 안에 반드시 super()가 있어야 한다.
      2. 서브클래스의 super() 호출 전에는 this를 참조할 수 없다.
      3. super()은 반드시 서브클래스에서만 호출해야한다.
  • 수퍼클래스의 메서드를 호출

    • Ex) super.sayHi()
    1. 자신을 참조하는 메서드(서브클래스)가 바인딩되어있는 객체(서브클래스.prototype)의 프로토타입(수퍼클래스.prototype)을 가리킨다.
    • 바인딩되어있는 객체는 [[HomeObject]]이며, 이는 ES6의 메서드 축약표현에만 정의되었으므로, super 참조도 메서드 축약표현만 가능하다.
    1. 서브클래스의 정적 메서드 내에서 super은 수퍼클래스의 정적 메서드를 가리킨다.
  • 수퍼클래스와 서브 클래스의 협력을 통한 인스턴스 생성과정

    1. 서브클래스에서의 super 호출

      • [[ConstructorKind]] 내부 슬롯을 통해 상속받은 클래스를 구분
        • (!상속받음 ? "base" : "derived")
      • 수퍼클래스에서 인스턴스 생성
        • 서브클래스의 위임
        • super을 반드시 맨앞에 호출하는 이유
    2. 수퍼클래스의 인스턴스 생성과 this 바인딩

      • this는 생성할 인스턴스인 서브클래스 인스턴스를 가리킨다.
      • new.target은 호출한 자신을 호출한 서브클래슬르 가리킨다.
    3. 수퍼클래스의 인스턴스 초기화

      • 인스턴스 프로퍼티 추가 & 초기값으로 초기화
    4. 서브클래스 constructor로의 복귀와 this바인딩

      • 수퍼클래스가 반환한 인스턴스에 this 바인딩
    5. 서브클래스의 인스턴스 초기화

      • 인스턴스 프로퍼티 추가 & 초기값으로 초기화
    6. 인스턴스 반환

표준 빌트인 생성자 함수 확장

  • 표준 빌트인 생성자 함수 역시도 동적 확장이 가능하다.
  • 빌트인 생성자 함수의 서브클래스에서 실행한 빌트인 생성자 함수를 반환하는 메서드는 서브클래스를 반환하도록 바뀐다.
    • 왜냐하면 서브클래스가 호출했기 때문이다.
    • 이를 막기위해서는 Symbol.species를 사용해야 한다.

느낀점

  • 생성자 함수와 class의 차이점이 상속관련하여 햇갈렸는데, 상속 방법은 모두 프로토타입을 이용하였지만 상속 목적이 인스턴스 생성 | 새로운 클래스 생성 이라는 측면에서 다르다는 걸 알게되었다.
    • 중요한 개념같아서 활용해볼 수 있도록 노력해야겠다.

0개의 댓글