[Modern JS Deep Dive] CH25-클래스1

Boo Sung Jun·2022년 7월 26일
0

JavaScript

목록 보기
17/27
post-thumbnail

Modern JavaScript Deep Dive 스터디 - CH25 클래스

참고 자료: ⟪모던 자바스크립트 Deep Dive⟫"(이웅모 지음,위키북스, 2020)


1. 클래스는 프로토타입의 문법적 설탕?

  • 자바스크립트는 프로토타입 기반 객체지향 언어 -> 클래스가 필요없는 객체지향 프로그래밍 언어
  • => 다른 객체지향 언어와 차이점에 있어 혼란 -> ES6에서 클래스를 도입

클래스 vs 생성자 함수

  • 클래스new 연산자 없이 호출하면 에러가 발생. 그러나 생성자 함수를 new 연산자 없이 호출하면 일반 함수로서 호출
  • 클래스는 상속을 지원하는 extends와 super 키워드를 제공
  • 클래스는 호이스팅이 발생하지 않는 것 처럼 동작. 함수 선언문으로 선언한 생성자 함수는 함수호이스팅, 함수 표현식으로 선언한 생성자 함수는 변수 호이스팅이 발생
  • 클래스 내의 모든 코드는 암묵적 strict mode로 지정되고, 해제할 수 없음
  • 클래스의 constructor, 프로토타입 메서드, 정적 메서드는 모두 프로퍼티 어티리뷰트 [[Enumeralble]]의 값이 false -> 열거 불가
  • 클래스는 생성자 함수의 문법적 설탕이라기 보단 새로운 객체 생성 매커니즘

2. 클래스의 정의

  • class 키워드를 사용해 정의
  • 클래스 이름은 파스칼 케이스를 사용하는 것이 일반적
  • 클래스는 일급 객체
    • 무명의 리터럴로 생성 가능. 즉, 런타임에 생성이 가능
    • 변수나 자료구조(객체, 배열 등)에 저장 가능
    • 함수의 매개변수에게 전달 가능
    • 함수의 반환값으로 사용 가능
// 익명 클래스 표현식
const Person = class {};

// 기명 클래스 표현식
const Person = class MyClass {};

3. 클래스 호이스팅

  • 클래스는 함수로 평가 됨

  • 변수 선언, 함수 정의와 마찬가지로 호이스팅이 발생

    • BUT 호이스팅이 발생하지 않는 것처럼 동작
    • let, const 키워드로 선언한 변수처럼 호이스팅 되어 선언과 초기화가 분리되어 진행되기 때문
    • TDZ(일시적 사각지대)에 빠지게 되어 호이스팅이 발생하지 않는 것처럼 동작
const Person = "";

{
  // 호이스팅이 발생하지 않는다면 ''이 출력되어야 한다.
  console.log(Person);
  // ReferenceError: Cannot access 'Person' before initialization

  // 클래스 선언문
  class Person {}
}
  • 소스코드 평가과정 즉, 런타임 이전에 먼저 평가되어 함수 객체를 생성
    • 이때 클래스가 평가되어 생성된 함수 객체는 생성자 함수로서 호출할 수 있는 함수, 즉 constructor
    • 생성자 함수로서 호출할 수 있는 함수는 함수 정의가 평가되어 함수 객체를 생성하는 시점에 프로토타입도 더불어 생성

4. 인스턴스 생성

  • 클래스는 생성자 함수이며, new 연산자와 함께 생성되어 인스턴스를 생성
  • 인스턴스 생성 시, 반드시 new 연산자와 함께 호출해야 함
  • 클래스 표현식으로 정의된 클래스 경우, 클래스를 가리키는 식별자를 사용해 인스턴스를 생성
const Person = class MyClass {};

// 함수 표현식과 마찬가지로 클래스를 가리키는 식별자로 인스턴스를 생성해야 한다.
const me = new Person();

// 클래스 이름 MyClass는 함수와 동일하게 클래스 몸체 내부에서만 유효한 식별자다.
console.log(MyClass); // ReferenceError: MyClass is not defined

const you = new MyClass(); // ReferenceError: MyClass is not defined

5. 메서드

  • 클래스 몸체에서 정의할 수 있는 메서드는 세 가지가 있음
    1. constructor
    2. 프로토타입 메서드
    3. 정적 메서드

1) constructor

  • 인스턴스를 생성하고 초기화
class Person {
  // 생성자
  constructor(name) {
    // 인스턴스 생성 및 초기화
    this.name = name;
  }
}
  • 클래스 내에 최대 한개만 존재
  • constructor는 생략 할 수 있음
    • 생략하면 빈 객체를 생성
  • 별도의 반환문을 갖지 않아야 함
    • return을 사용 안하는 것이 바람직함
    • this가 아닌 다른 객체를 명시적으로 return하면 해당 객체가 반환
    • 원시값을 return하면 무시하고 암묵적으로 this 반환
  • 함수와 동일하게 프로토타입과 연결되어 있으며 자신의 스코프 체인을 구성

2) 프로토타입 메서드

  • 생성자 함수와 다르게 클래스는 프로토타입 메서드를 사용하지 않아도 기본적으로 프로토메서드 타입이 됨
class Person {
  // 생성자
  constructor(name) {
    // 인스턴스 생성 및 초기화
    this.name = name;
  }

  // 프로토타입 메서드
  sayHi() {
    console.log(`Hi! My name is ${this.name}`);
  }
}

const me = new Person("Lee");
me.sayHi(); // Hi! My name is Lee
  • 클래스가 생성한 인스턴스는 프로토타입 체인의 일원이 됨
  • 프로토타입 메서드는 프로토타입 객체로 바인딩
  • 인스턴스는 프로토타입 메서드를 상속받아 사용 가능
// me 객체의 프로토타입은 Person.prototype이다.
Object.getPrototypeOf(me) === Person.prototype; // -> true
me instanceof Person; // -> true

// Person.prototype의 프로토타입은 Object.prototype이다.
Object.getPrototypeOf(Person.prototype) === Object.prototype; // -> true
me instanceof Object; // -> true

// me 객체의 constructor는 Person 클래스다.
me.constructor === Person; // -> true

3) 정적(static) 메서드

  • 인스턴스를 생성하지 않아도 호출할 수 있는 메서드
  • static 키워드를 붙여서 생성
class Person {
  // 생성자
  constructor(name) {
    // 인스턴스 생성 및 초기화
    this.name = name;
  }

  // 정적 메서드
  static sayHi() {
    console.log("Hi!");
  }
}
  • 클래스에 바인딩됨
  • 정적 메서드는 인스턴스로 호출할수 없고 클래스로 호출
    • 정적 메서드가 바인딩 된 클래스는 인스턴스의 프로토타입 체인상에 존재하지 않기 때문

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

  • 자신이 속해 있는 프로토타입 체인이 다름
  • 정적 메서드는 클래스로 호출하고, 프로토타입 메서드는 인스턴스로 호출
  • 정적 메서드는 인스턴스 프로퍼티를 참조할 수 없지만, 프로토타입 메서드는 인스턴스 프로퍼티를 참조할 수 있음
  • this 바인딩이 다름
    • 정적 메서드 -> 클래스
    • 프로토타입 메서드 -> 인스턴스(자신을 호출한 객체)

5) 클래스에서 정의한 메서드의 특징

  • function 키워드를 생략한 메서드 축약 표현을 사용
  • 메서드를 정의할 때는 콤마가 필요 없음
  • 암묵적으로 strict mode 실행
  • for ... in 문이나 Object.keys 메서드 등으로 열거 불가
    • 프로퍼티 어트리뷰트 [[Enumerable]]의 값이 false
  • 내부 메서드 [[Construct]]를 갖지 않는 non-constructor -> new연산자와 함께 호출할 수 없음

0개의 댓글