[Javascript] 클래스(Class)

SungWoo·2024년 10월 28일

자바스크립트 공부

목록 보기
16/42
post-thumbnail

ES5에서는 생성자 함수와 프로토타입을 통해 객체지향 언어의 상속을 구현해왔다. 이후 ES6에서 클래스 기반 언어에 익숙한 프로그래머들이 더욱 빠르게 학습할 수 있도록 클래스 기반 객체지향 프로그래밍 언어와 매우 흡사한 새로운 객체 생성 메커니즘인 클래스를 제시하였다.

단, 클래스와 생성자 함수는 모두 프로토타입 기반의 인스턴스를 생성하지만 정확히 동일하게 동작하지는 않는다. 클래스는 생성자 함수보다 엄격하며 생성자 함수에서는 제공하지 않는 기능도 제공한다.

클래스(Class)

  • 자바스크립트 클래스는 객체 지향 프로그래밍을 구현하기 위한 템플릿이다.
  • 클래스는 객체를 생성하는 청사진 역할을 하며, 재사용 가능한 코드 구조를 만들 수 있게 해준다.
  • ES6에서 도입되었으며, 기존 프로토타입 기반의 객체 지향 프로그래밍을 보다 직관적이고 명확하게 사용할 수 있도록 해준다.

1. 클래스 정의

  • 클래스를 정의하려면 class 키워드를 사용한다.
  • 클래스 이름은 생성자 함수와 마찬가지로 파스칼 케이스로 작성하는 것이 일반적이다.
  • 클래스 몸체에서 정의할 수 있는 메서드는 constructor(생성자), 프로토타입 메서드, 정적 메서드의 세가지가 있다.
class Person {
  // 생성자
  constructor(name, age) {
    this.name = name; // 클래스의 프로퍼티
    this.age = age;
  }

  // 프로토타입 메서드
  sayHi() { 
    console.log(`Hello, my name is ${this.name}.`);
  }
  
  // 정적 메서드
  static sayAge() { 
    console.log(`I am ${this.age} years old.`);
  }
}
  • Person 클래스는 두 개의 프로퍼티(name, age)와 sayHi라는 프로토타입 메서드, sayAge라는 정적 메서드를 가지고 있다.

2. 인스턴스 생성

  • 클래스를 사용하려면 new 키워드를 사용하여 인스턴스를 생성한다.
const person1 = new Person('Sean', 25);

person1.sayHi(); // "Hello, my name is Sean."
person1.sayAge(); // "I am 25 years old."

3. 메서드

1) constructor(생성자)

  • constructor는 인스턴스를 생성하고 초기화하기 위한 특수한 메서드이다.
  • constructor는 이름을 변경할 수 없다.
  • constructor는 클래스 내에 최대 1개만 존재할 수 있다.
  • constructor는 생략할 수 있다.
  • constructor는 별도의 반환문을 갖지 않아야 한다.
    new 키워드와 함께 클래스가 호출되면 생성자 함수와 동일하게 this, 즉 인스턴스를 반환한다.
    ↪ 만약 this가 아닌 다른 객체를 명시적으로 반환하면 this, 즉 인스턴스가 반환되지 못하고 return 문에 명시된 객체가 반환된다.
    ↪ 명시적으로 원시값을 반환하면 무시되고 암묵적으로 this가 반환된다.

2) 프로토타입 메서드

  • 클래스 몸체에 정의한 메서드는 기본적으로 프로토타입 메서드가 된다.

3) 정적 메서드

  • 정적 메서드는 인스턴스를 생성하지 않아도 호출할 수 있는 메서드를 말한다.
  • 메서드에 static 키워드를 붙이면 정적 메서드(클래스 메서드)가 된다.

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

  1. 두 메서드는 자신이 속해 있는 프로토타입 체인이 다르다.
  2. 프로토타입 메서드는 인스턴스로 호출하고 정적 메서드는 클래스로 호출한다.
  3. 프로토타입 메서드는 인스턴스 프로퍼티를 참조할 수 있지만 정적 메서드는 인스턴스 프로퍼티를 참조할 수 없다.

5) 접근자 프로퍼티

  • 접근자 프로퍼티는 자체적으로 값([[Value]] 내부 슬롯)을 갖지 않고 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 사용하는 접근자 함수로 구성된 프로퍼티다.
  • 속성에 접근하거나 수정하기 위한 프로퍼티
  • 주로 getset 키워드를 사용하여 정의하며, 객체의 속성에 대한 접근 방식을 제어할 수 있다.
class Person {
  constructor(name, age) {
    this._name = name; // 내부 속성 (관습적으로 언더스코어 사용)
    this._age = age;
  }

  get name() {
    return this._name; // 이름을 가져오는 getter
  }

  set name(newName) {
    this._name = newName; // 이름을 설정하는 setter
  }

  get age() {
    return this._age; // 나이를 가져오는 getter
  }

  set age(newAge) {
    if (newAge >= 0) {
      this._age = newAge; // 유효한 나이 설정
    } else {
      console.error("Age cannot be negative.");
    }
  }
}

const person1 = new Person('Sean', 25);
console.log(person1.name); // "Sean"
person1.age = 30; // 나이 수정
console.log(person1.age); // 30
person1.age = -5; // "Age cannot be negative."

4. Private 필드 정의

  • private 필드는 클래스의 내부 데이터(상태)를 보호하기 위해 사용된다.
  • 필드는 클래스의 메서드 내에서만 접근할 수 있으며, 외부에서는 접근이 불가하다.
  • ES13부터 # 기호를 사용하여 private 필드를 정의할 수 있게 됐다.
class Person {
  // Private 필드 정의
  #name;
  #age;

  constructor(name, age) {
    this.#name = name; // Private 필드에 값 할당
    this.#age = age;
  }

  // Public 메서드
  greet() {
    console.log(`Hello, my name is ${this.#name} and I am ${this.#age} years old.`);
  }
}

const person1 = new Person('Sean', 25);
person1.greet(); // "Hello, my name is Sean and I am 25 years old."

// 외부에서 private 필드 접근 시도
console.log(person1.#name); // SyntaxError: Private field '#name' must be declared in an enclosing class

5. 상속에 의한 클래스 확장

  • extends 키워드를 사용하여 클래스를 상속할 수 있다.
  • 자식 클래스는 부모 클래스의 프로퍼티와 메서드를 상속받아 사용할 수 있다.
  • 필요에 따라 추가적인 프로퍼티나 메서드를 정의하여 기능을 확장할 수 있다.
class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(`${this.name} makes a noise.`);
  }
}

// Animal 클래스를 상속하는 Dog 클래스
class Dog extends Animal {
  constructor(name, breed) {
    super(name); // 부모 클래스의 생성자 호출
    this.breed = breed; // 추가 속성 정의
  }

  // 부모 메서드 오버라이드
  speak() {
    console.log(`${this.name} barks.`);
  }

  // 추가 메서드
  displayBreed() {
    console.log(`Breed: ${this.breed}`);
  }
}

const dog1 = new Dog('Rex', 'Golden Retriever');
dog1.speak(); // "Rex barks."
dog1.displayBreed(); // "Breed: Golden Retriever"

// Animal 클래스의 인스턴스 생성
const animal1 = new Animal('Generic Animal');
animal1.speak(); // "Generic Animal makes a noise."

super 호출

super를 호출하면 수퍼 클래스의 constructor(super-constructor)를 호출한다.

  • super 키워드는 함수처럼 호출할 수 있다.
  • super 키워드는 this와 같이 식별자처럼 참조할 수 있는 특수한 키워드다.
  • super를 참조하면 수퍼클래스의 메서드를 호출할 수 있다.
profile
어제보다 더 나은

0개의 댓글