클래스

정민교·2023년 7월 11일
0

javascript

목록 보기
7/16

📒클래스

자바스크립트는 프로토타입 기반 객체지향 언어라 클래스가 필요없다.

자바스크립트 클래스는 함수이며 프로토타입 기반 패턴은 클래스 기반 패턴처럼 사용할 수 있도록 하는 syntatic sugar다.

클래스도 함수이기 때문에 일급 객체다.

✔️클래스 정의

클래스 정의는 클래스 선언문, 클래스 표현식(익명, 기명 클래스 표현식)으로 정의 가능하다.

✔️클래스 호이스팅

클래스 선언문으로 클래스를 정의하면, 소스 코드 평가 과정에 먼저 실행되어 함수 객체를 생성한다.

생성된 함수 객체는 constructor라서 함수 객체가 생성되는 시점에 프로토타입도 같이 생성된다.

따라서 생성자 함수처럼 호이스팅이 발생하지만, 클래스는 클래스 정의 이전에 참조할 수 없다.

✔️인스턴스 생성

클래스는 생성자 함수이며 new 연산자와 함께 호출되어 인스턴스를 생성한다.

생성자 함수와 달리 반드시 new와 함께 호출되어야 한다.

new 연산자와 함께 호출되지 않으면 에러가 발생한다.

클래스도 함수와 마찬가지로 식별자로 호출한다.(기명 함수 표현식으로 정의된 함수를 식별자에 할당하는 경우를 생각하면 된다.)

✔️메서드

클래스 몸체에서 정의할 수 있는 메서드는 생성자, 프로토타입 메서드, 인스턴스 메서드, 정적 메서드다.

📌constructor

인스턴스를 생성하고 초기화하는 특수한 메서드다.

constructor 내부에서 this에 추가한 프로퍼티는 클래스가 생성할 인스턴스의 프로퍼티가 된다.

주의해야 할 점

  • constructor는 하나의 클래스에 하나만 존재한다.
  • constructor를 작성하지 않으면 암묵적으로 빈 constructor가 정의된다.
  • constructor 내부에서 별도의 반환문을 쓰면 안된다.(생성자 함수에서의 return문과 똑같이 작동)

📌프로토타입 메서드

클래스 몸체에 정의한 메서드다.

클래스 몸체에 정의한 메서드는 인스턴스의 프로토타입에 존재하는 프로토타입 메서드가 된다.

📌정적 메서드

인스턴스를 생성하지 않아도 호출할 수 있는 메서드다

static 키워드를 붙여 클래스 몸체에 메서드를 정의하면 정적 메서드가 된다.

이는 클래스가 평가되어 생성되는 함수 객체의 메서드가 된다.

정적 메서드는 인스턴스를 통해 호출할 수 없다.

표준 빌트인 객체 Math, Number, JSON, Object, Reflect 등은 다양한 정적 메서드를 가지고 있으며, 이 정적 메서드들은 애플리케이션 전역에서 사용할 수 있는 유틸리티 함수다.

👉정적 팩토리 메서드(팩토리 컨스트럭터)

static 키워드를 쓰는 이유 중 하나는 정적 패토리 메서드 패턴을 사용할 수 있기 때문입니다.

class IdolModel{
    name;
    year;

    constructor(name, year){
        this.name = name;
        this.year = year;
    }

    static fromObject(object){
        return new IdolModel(
            object.name,
            object.year,
        );
    }

    static fromList(list){
        return new IdolModel(
            list[0],
            list[1],
        );
    }
}

생성자 대신 사용할 수 있습니다. 특정 데이터로부터 인스턴스를 생성할 수 있도록 템플릿화 할 수 있는 장점이 있습니다.

const yuJin2 = IdolModel.fromObject({
    name: '안유진',
    year: 2003,
});
console.log(yuJin2); // IdolModel {name: '안유진', year: 2003}

const wonYoung = IdolModel.fromList(
    [
        '장원영',
        2003,
    ]
);
console.log(wonYoung); // IdolModel {name: '장원영', year: 2003}

참고
https://inpa.tistory.com/entry/GOF-%F0%9F%92%A0-%EC%A0%95%EC%A0%81-%ED%8C%A9%ED%86%A0%EB%A6%AC-%EB%A9%94%EC%84%9C%EB%93%9C-%EC%83%9D%EC%84%B1%EC%9E%90-%EB%8C%80%EC%8B%A0-%EC%82%AC%EC%9A%A9%ED%95%98%EC%9E%90

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

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

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

  1. 메서드 축약 표현을 사용해서 정의한다.
  2. 암묵적으로 strict mode로 실행된다.
  3. for...in문이나 Object.keys 메서드 등으로 열거할 수 없다.(프로퍼티 어트리뷰트 [[Enumerable]]이 false다.
  4. non-constructor다. new 연산자와 함께 호출 불가.

✔️프로퍼티

📌인스턴스 프로퍼티

인스턴스 프로퍼티는 constructor 내부에서 정의하여 초기화한다.

클래스 필드 정의로 constructor 밖에서도 정의할 수 있다.

📌접근자 프로퍼티

클래스에서도 접근자 프로퍼티 getter, setter를 정의할 수 있다.

setter는 단 하나의 값만 할당받기 때문에 단 하나의 매개변수만 선언할 수 있다.

📌클래스 필드 정의

클래스 기반 객체지향 언어의 클래스 필드처럼 인스턴스 변수를 정의할 수 있다.

함수는 일급 객체이므로 함수를 클래스 필드에 할당할 수 있다. 클래스 필드에 메서드를 할당하면 인스턴스 메서드가 된다.(권장하지 않음)

📌private 접근 제한자

#을 클래스 필드와 함께 사용해서 private 필드를 정의할 수 있다.

private 필드는 접근자 프로퍼티를 통해서 접근 가능하다.

📌static 필드 정의

static 메서드와 마찬가지로 static 키워드를 사용해 정적 필드를 정의할 수 있다.

✔️클래스 상속

상속에 의한 클래스 확장은 프로토타입 기반 상속과는 다른 개념이다.

프로토타입 기반 상속은 프로토타입 체인을 통해 프로퍼티와 메서드를 상속한다.

상속에 의한 클래스 확장은 기존 클래스를 상속받아 새로운 클래스를 확장한다.

📌extends 키워드

extends 키워드를 사용하여 상속을 통한 클래스 확장이 가능하다.

수퍼클래스와 서브클래스는 인스턴스의 프로토타입 체인 뿐만 아니라 클래스 간의 프로토타입 체인도 생성한다.

이를 통해 프로토타입 메서드, 정적 메서드 모두 상속이 가능하다.

또한 클래스는 생성자 함수를 상속할 수도 있다.

extends 키워드 다음에는 [[Construct]] 내부 메서드를 갖는 함수 객체로 평가될 수 있는 모든 표현식을 사용할 수 있다. 이를 활요하여 동적으로 상속할 대상을 결정할 수도 있다.

📌서브클래스의 constructor

서브클래스에서 constructor를 생략하면 다음과 같은 constructor가 암묵적으로 정의된다.

constructor(...args) {
  super(...args);
}

📌super 키워드

  • super를 호출하면 수퍼 클래스의 constructor를 호출한다.
  • super를 참조하면 수퍼클래스의 메서드를 호출할 수 있다.

👉super 호출

서브클래스에서 constructor를 생략하지 않는 경우 반드시 super()를 호출해야한다.

super를 호출하기 전에는 this를 참조할 수 없다.

👉super 참조

메서드 내에서 super를 참조하면 수퍼클래스의 메서드를 호출할 수 있다.

메서드는 내부 슬롯 [[HomeObject]]를 가지고, 자신을 바인딩하고 있는 객체를 가리킨다.

[[HomeObject]]는 오직 ES6 메서드 축약 표현으로 정의된 함수만 갖는다.

[[HomeObject]]를 가지는 함수만 super 참조가 가능하기 때문에 ES6 메서드만 super 참조가 가능하다.

서브클래스의 정적 메서드 내에서 super 참조를 통한 메서드 호출은 수퍼클래스의 정적 메서드를 호출한다.

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

  1. 서브클래스의 super 호출

자바스크립트 엔진이 클래스를 평가할 때 수퍼클래스인지 서브클래스인지 구분하기 위해 내부 슬롯 [[ConstructorKind]]를 확인한다.

[[ConstructorKind]] 내부슬롯은 상속클래스면 "derived"를 상속 클래스가 아니라면 "base"를 값으로 갖는다.

new 연산자와 함께 호출했을 때 [[ConstructorKind]] 값을 확인해서 수퍼클래스와 서브클래스의 호출이 구분된다.

서브클래스는 자신이 직접 인스턴스를 생성하지 않고 수퍼클래스에게 인스턴스 생성을 위임한다. 그렇기 때문에 반드시 서브클래스에서 super를 호출해야 한다.

  1. 수퍼클래스의 인스턴스 생성과 this 바인딩

암묵적으로 인스턴스를 생성하는 것은 수퍼클래스지만 new 연산자와 함께 호출된 클래스는 서브클래스다.

즉, new.target은 서브클래스를 가리키기 때문에 암묵적으로 생성된 인스턴스는 서브클래스가 생성한 것으로 처리된다.(this 가 서브클래스의 인스턴스임)

  1. 수퍼클래스의 인스턴스 초기화

  2. 서브클래스 constructor로 복귀 및 this 바인딩

super가 반환한 인스턴스가 this에 바인딩된다. 서브클래스는 별도의 인스턴스를 생성하지 않고 super가 반환한 인스턴스를 this에 바인딩하여 그대로 사용한다.

  1. 서브클래스의 인스턴스 초기화

  2. 인스턴스 반환

📌표준 빌트인 생성자 함수 확장

extends 키워드 뒤에 올 수 있는 것은 클래스 뿐만 아니라 constructor인 함수 객체로 평가될 수 있는 모든 표현식을 사용할 수 있다.

따라서 String, Number, Array 같은 표준 빌트인 객체도 extends 키워드 뒤에 사용할 수 있다.

profile
백엔드 개발자

0개의 댓글