Programming Language/JavaScript, TypeScript

# 021. 클래스

Adrian Kim 2024. 2. 21. 00:04
  • 자바스크립트는 프로토타입 기반의 객체지향 언어임.
  • 다른 객체 지향 언어와는 달리, ES5까지는 클래스가 없고 생성자 함수와 프로토타입을 통해 객체지향 언어의 상속을 구현함.
  • ES6에서 도입된 클래스는 프로토타입 기반 객체지향 모델과 전혀 다른 문법이 아니며, 프로토타입 기반 패턴을 클래스 형태로 사용할 수 있게 해주는 문법적 설탕이라는 의견도 있음.
  • 클래스는 생성자 함수와 매우 유사하게 동작하지만, new 연산자 필수여부, extend, super 키워드, 암묵적 엄격모드, 열거 여부 등 몇가지 차이가 존재함.
  • 클래스는 단순한 문법적 설탕이 아니라, 기존 프로토타입 기반 패턴을 사용해야 할 경우 보다 간편하고 명료한 코딩을 할 수 있게 해주는 새로운 객체 생성 방식이라고 보는 것이 합당할 것임.

📌 클래스의 정의

  • 클래스는 일급 객체로서, 함수의 반환값으로 사용할 수 있고, 변수에 할당할 수 있으며, 함수의 인자로 전달할 수 있음.
class Person {
  // 생성자
  constructor(name) {
    // 인스턴스 생성 및 초기화
    this.name = name;
  }

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

  // 정적 메서드
  static sayHello() {
    console.log('Hello!');
  }
}

// 인스턴스 생성
const me = new Person('Lee');

// 인스턴스의 프로퍼티 참조
console.log(me.name); // Lee

// 프로토타입 메서드 호출
me.sayHi(); // Hi! My name is Lee

// 정적 메서드 호출
Person.sayHello(); // Hello!

📌 클래스 호이스팅

  • 클래스 선언문으로 정의한 클래스는 함수 선언문과 동일하게 호이스팅이 발생함.
  • 클래스 선언문 이전에 클래스를 참조하면 참조 에러가 발생함. 호이스팅이 발생하지 않는 것 처럼 동작하지만 실제로는 호이스팅이 발생함.
  • var, let, const, function, class 키워드를 사용하여 선언한 모든 식별자는 호이스팅이 발생함. 모든 선언문은 런타임 이전에 먼저 실행되기 때문임.

📌 인스턴스 생성

  • 클래스는 생성자 함수와 달리 new 연산자 없이 호출하면 에러가 발생함.

📌 메서드

  • 클래스는 생성될 인스턴스의 프로퍼티를 정의하는 필드메서드로 구성됨.(ES2020 이후)
  • 클래스 몸체에서 정의할 수 있는 메서드는 constructor, 프로토타입 메서드, 정적 메서드가 있음.
  • constructor는 클래스로 인스턴스를 생성하고 초기화하기 위한 특수한 메서드로, 이름 변경이 불가능함.
  • 프로토타입 메서드는 프로토타입에 바인딩되어 인스턴스의 프로토타입 체인을 통해 사용할 수 있음.
  • 정적 메서드는 인스턴스를 생성하지 않아도 호출할 수 있는 메서드임. 프로토타입 메서드와 달리 인스턴스의 프로토타입 체인에 바인딩되지 않고 클래스로 호출됨.
  • 클래스에서 정의한 메서드는 암묵적으로 엄격모드로 실행되고, 축약 표현을 사용해야하며, 객체 리터럴과는 다르게 콤마로 메서드를 구분하지 않음.
  • 또한 for...in 문이나 Object.keys 메서드 등으로 열거할 수 없으며, non-constructor이기 때문에 new 연산자와 함께 호출이 불가능함.

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

  • 클래스의 인스턴스 생성 과정은 생성자 함수와 유사함.
  • 먼저 new 연산자와 함께 클래스를 호출하면 암묵적으로 빈 객체(인스턴스)가 생성되고, 인스턴스의 프로토타입 체인이 생성되고, 이후 this에 인스턴스가 바인딩됨.
  • constructor의 내부 코드가 실행되어 this에 바인딩된 인스턴스를 초기화하고, this에 바인딩되어 있는 인스턴스에 프로퍼티를 추가하여 인스턴스의 프로퍼티 값을 초기화함.
  • 이와같은 처리가 모두 끝나면 완성된 인스턴스가 바인딩된 this가 암묵적으로 반환됨.

📌 프로퍼티

  • 인스턴스의 프로퍼티는 constructor 내부에서 정의해야함.
  • gettersetter 등의 접근자 프로퍼티는 그자체로 값을 갖지 않고, 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 사용됨.
  • 클래스 몸체에서 프로퍼티를 정의한 부분을 클래스 필드라고 함.
  • 클래스 필드에서 정의한 프로퍼티는 외부 접근을 막는 private 접근 제한자를 통해 간접적으로 캡슐화를 구현할 수 있음.
  • static 키워드를 사용하여 정적 프로퍼티를 정의할 수 있음.

📌 상속에 의한 클래스 확장

  • 프로토타입 기반 상속은 프로토타입 체인을 통해 다른 객체의 자산을 상속받는 개념이지만, 상속을 통해 클래스를 확장하는 것은 클래스를 상속받아 새로운 클래스를 확장하는 것을 의미함.
  • 상속을 통해 확장된 클래스는 부모 클래스의 기능을 그대로 사용할 수 있으며, 부모 클래스의 기능을 재정의하거나 확장할 수 있음.
  • 상속을 통해 클래스를 확장하려면 extends 키워드를 사용하여 상속받을 클래스를 지정해야함.
  • super키워드는 부모 클래스를 참조할 때 사용함.

예상질문

  1. 자바스크립트의 클래스에 대해 아는대로 설명해주세요.

레퍼런스

  • 모던자바스크립트 딥다이브(이웅모 저)

'Programming Language > JavaScript, TypeScript' 카테고리의 다른 글

#023. Promise  (0) 2024.02.27
#022. 클로저  (0) 2024.02.21
#020. 실행 컨텍스트  (0) 2024.02.05
#019. this  (0) 2024.02.05
#018. 프로토타입  (0) 2024.01.28