[TIL]JavaScript_클래스

Sohee Yeo·2023년 6월 16일
0
post-thumbnail

클래스(Classes)

C++이나 Java 같은 클래스 기반 객체지향 프로그래밍 언어는 클래스를 통해 상속한다. 하지만 자바스크립트는 클래스가 없고, 프로토타입 기반으로 객체 복제를 통해 객체를 생성한다.

ES6에서 자바스크립트의 클래스가 도입되었는데, 클래스 기반 객체지향 프로그래밍 언어와 매우 비슷한 문법 구조를 가지고 있다. 하지만 클래스는 함수이며 기존 프로토타입 기반 패턴을 클래스 기반 패턴처럼 사용할 수 있는 문법적 설탕이라고도 한다.

클래스를 통해 여러 객체를 만들 수 있는데, 쉽게 말해 클래스 = 붕어빵 틀, 객체 = 붕어빵이라고 할 수 있다.

생성자 함수와 클래스 문법의 차이

// 생성자 함수
function User({name, age}) {
  this.name = name;
  this.age = age;
}
// prototype에 메서드 추가
User.prototype.sayHello = function() {
  return `Hello, ${this.name}!`;
};

const user = new User({name: 'Lee', age: 13});
console.log(user.sayHello());

// Hello, Lee!

클래스는 class 키워드를 사용해 생성하고, new 연산자와 함께 호출하면 내부에서 정의한 메서드가 들어있는 객체가 생성된다.

// class 문법
class User {
  // constructor 키워드로 생성자 정의
  constructor({name, age}) {
    this.name = name;
    this.age = age;
  }
  // prototype에 메서드 추가
  sayHello() {
    return `Hello, ${this.name}!`;
  }
}

const user = new User({name: 'Lee', age: 13});
console.log(user.sayHello());

// Hello, Lee!

클래스 정의

클래스 선언

클래스를 선언하기 위해 class 키워드와 클래스 이름(예시에서 User)을 함께 사용한다. 클래스 내부의 constructor 메서드는 클래스 안에 한 개만 존재할 수 있다. constructor 내부에서 인스턴스의 생성 및 초기화가 이루어진다.

class User{
  constructor({name, age}) {
    this.name = name;
    this.age = age;
  }
}

메서드 정의

• 프로토타입 메서드

생성자 함수에서 프로토타입 메서드를 생성하기 위해 명시적으로 prototype 프로퍼티에 추가해야 하지만, 클래스에서 정의한 메서드는 prototype 프로퍼티에 추가하지 않아도 자동으로 프로토타입 메서드가 된다.

class User{
  constructor({name, age}) {
    this.name = name;
    this.age = age;
  }
  // 프로토타입 메서드
  sayHello() {
    return `Hello, ${this.name}!`;
  }
}

const user = new User({name: 'Lee', age: 13});
console.log(user.sayHello());

// Hello, Lee!

• 정적 메서드

정적 메서드는 인스턴스를 생성하지 않아도 호출할 수 있는 메서드이다. 클래스에서 static 키워드를 붙이면 정적 메서드가 된다. 정적 메서드는 프로토타입이 아닌 클래스에 바인딩 된 메서드가 되기 때문에 인스턴스로 호출하지 않고 클래스로 호출한다.

class User{
  constructor({name, age}) {
    this.name = name;
    this.age = age;
  }
  // 프로토타입 메서드
  sayHello() {
    return `Hello, ${this.name}!`;
  }
  // 정적 메서드
  static welcome() {
    return 'Welcome to our shop.';
  }
}

const user = new User({name: 'Lee', age: 13});
console.log(user.sayHello()); // Hello, Lee!

// 정적 메서드를 인스턴스로 호출하면 에러
console.log(user.welcome()); // Uncaught TypeError: user.welcome is not a function

// 정적 메서드는 인스턴스 없이 호출
console.log(User.welcome()); // Welcome to our shop.

프로토타입 메서드와 정적 메서드는 다음과 같은 차이가 있다.

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

클래스 상속

extends 키워드

extends 키워드는 클래스의 자식 클래스를 생성하기 위해 사용된다.

// 수퍼(부모)클래스
class Parent{}

// 서브(자식)클래스
// extends 키워드로 상속
class Child extends Parent{}

상속을 통해 확장된 클래스를 서브 클래스라 하고, 서브 클래스에게 상속한 클래스를 수퍼 클래스라 한다. 프로토타입 메서드, 정적 메서드 모두 상속이 가능하다. 자식 클래스에서 부모 클래스의 속성, 메서드를 사용할 수 있게 된다.

class Animal{
  constructor(name, age) {
    this.name = name;
  }
  
  sleep() {
    return `${this.name} is sleeping.`;
  }
}

// Animal로부터 상속
class Cat extends Animal{
  cry() {
    return `${this.name} is crying.`;
  }
}

let myCat = new Cat('My cat');

console.log(myCat.sleep()); // My cat is sleeping.
console.log(myCat.cry()); // My cat is crying.

extends 키워드는 프로토타입 기반으로 동작한다. 위의 예제에서 Cat.prototype.[[Prototype]]Animal.prototype으로 설정하고, Cat.prototype에서 메서드를 찾지 못하면 Animal.prototype에서 메서드를 가져온다.

super 키워드

super 키워드는 함수처럼 호출할 수도 있고, this와 같이 식별자처럼 참조할 수 있는 키워드이다. super 키워드를 사용하면 부모 클래스의 생성자 함수나 메서드를 호출할 수 있다.
자식 클래스는 자신이 직접 인스턴스를 생성하지 않고 자식 클래스의 생성자 함수에서 super을 호출하여 부모 클래스에게 인스턴스 생성을 위임한다. 자식 클래스의 생성자 함수에서 super을 호출하기 전에는 this를 참조할 수 없다.

class Animal{
  constructor(name, age) {
    this.name = name;
  }
}

class Cat extends Animal{
  constructor(name) {
    super(name); // super 함수 호출로 부모 클래스 생성자 함수 호출
    this.age = age;
  }
}

let myCat = new Cat('My cat', 5);

console.log(myCat.name); // My cat
console.log(myCat.age); // 5

정리

  • 클래스 = 붕어빵 틀, 객체 = 붕어빵
  • class 키워드를 사용해 클래스 생성하고, new 연산자와 함께 호출하면 내부에서 정의한 메서드가 들어있는 객체가 생성된다.
  • constructor 내부에서 인스턴스의 생성 및 초기화가 이루어진다.
  • extends, super 키워드를 사용하여 상속한다.



참고

모던 자바스크립트 Deep Dive (도서)
https://ko.javascript.info/class
https://ko.javascript.info/class-inheritance
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes

profile
실패에 무딘 사람. 프론트엔드 개발자를 꿈꿉니다

0개의 댓글