JavaScript

[DeepDive] - 25장(클래스) 필요 내용 정리

클래스 정의

  • 클래스는 객체(인스턴스)를 생성하기 위한 템플릿이다.
  • 클래스는 선언식과 표현식으로 정의가 가능하다.
  • 표현식으로 정의할 수 있는 이유는, 클래스가 값처럼(데이터처럼) 자유롭게 사용될 수 있는 일급 객체라는 것을 의미한다.
class Base {}

const Base = class {};

const Base = class 
  • 클래스 몸체에 정의할 수 있는 메서드의 종류는 constructor(생성자), 프로토타입 메서드, 정적 메서드 3가지가 존재한다.
class Person{
  // 생성자 
  constructor(name, age, gender) {
    this.name = name;
    this.age = age;
    this.gender = age;
  }

  // 프로토타입 메서드
  sayHi(){
    return `hi, i'm ${this.name}`
  }

  // 정적 메서드
  static sayHello(){
    return "hello"
  }
}
  1. constructor
    • 인스턴스를 생성하고 초기화하기 위한, 특수 메서드(생성자 함수)
    • 이름 변경 X
    • 내부에서 this에 프로퍼티를 추가함으로써, 인스턴스에 필요한 프로퍼티 추가 가능
    • 클래스 내부 1개만 존재 가능, 생략 가능(생략을 할시, constructor(){}가 암묵적으로 정의)
    • ES6 이전의 생성자 함수에서처럼 내부에 원시값을 리턴할시 암묵적으로 this가 반환되며, 명시적으로 다른 객체를 리턴할 경우 명시한 해당 객체가 반환
  2. 프로토타입 메서드
    • 클래스 몸체에서 정의한 메서드는 인스턴스의 프로토타입에 존재하는 메서드로, 프로토타입 체인에 의해 상속받아 사용 가능
    • 프로토타입 메서드 내부 this는 인스턴스를 가리킴
  3. 정적 메서드
    • 클래스의 메서드로서 호출하여 사용 가능(인스턴스에서의 호출 X)
    • 정적 메서드 내부 this는 클래스를 가리킴

 

클래스 호이스팅

  • 클래스는 함수로 평가되며 클래스 선언문은 let과 const 키워드로 선언한 변수처럼 호이스팅이 일어난다. (선언 이전에 호출할 경우 참조 오류 발생)
// ReferenceError: Cannot access 'Person' before initialization
const person1 = new Person("neo", 10, "male")

class Person{
  // 생성자 
  constructor(name, age, gender) {
    this.name = name;
    this.age = age;
    this.gender = age;
  }

  // 프로토타입 메서드
  sayHi(){
    return `hi, i'm ${this.name}`
  }

  // 정적 메서드
  static sayHello(){
    return "hello"
  }
}

 

클래스의 인스턴스 생성 과정

  • 클래스의 인스턴스 생성 과정은, ES6 이전의 생성자 함수의 인스턴스 생성 과정과 동일하다.
class Person{
  constructor(name, age, gender) {
//     1. 암묵적으로 인스턴스 생성(빈 객체)
//     Person {...}
  console.log(this)     

//     2. this에 바인딩된 인스턴스  초기화
    this.name = name;
    this.age = age;
    this.gender = age;
//     3. 완성된 인스턴스가 바인딩된 this, 암묵적 반환
  }
}

 

상속에 의한 클래스 확장, super 키워드

  • extends 키워드를 통해 기존 클래스를 확장하여 사용이 가능하다.
  • super 키워드 통해, constructor 내부에서는 수퍼 클래스(상속을 받는 부모 클래스)의 constructor를 호출하여 재사용 및 확장이 가능하며, 메서드 내부에서는 수퍼 클래스의 메서드를 상속받아 그대로 사용이 가능하다.
  • 상속을 받는 서브 클래스의 constructor에서 super 호출 전에는 this를 참조할 수 없다. (서브 클래스는 자신이 인스턴스를 직접 생성하지 않고 수퍼 클래스에게 인스턴스 생성을 위임하기 때문이다. 따라서 super의 호출이 없으면 인스턴스의 생성 자체가 불가하기에 this가 바인딩이 되지 않으므로 참조가 불가하다.)
// 수퍼 클래스
class SuperClass {
  constructor(name,age) {
    this.name = name;
    this.age = age;
  }

  sayHi(){
        return `super ${this.name}`
  }
}

// SuperClass를 확장
class SubClass extends SuperClass { 
  // 기존 프로퍼티에 gender 프로퍼티 추가
    constructor(name,age,gender) { 

  // super 키워드를 통해 인스턴스 프로퍼티 확장
    super(name,age); 
    this.gender = gender;
  }

  sayHi(){
    // 메서드 내부 super를 통해 수퍼 클래스의 메서드 사용 가능
    return super.getSuperClassName() 
  }  
}

const subClass = new SubClass("sub",18,"male")
console.log(subClass)