본문 바로가기
Frontend/JavaScript

17. 클래스

by yerin.dev 2023. 12. 21.

클래스

  • 자바스크립트는 프로토타입 기반 객체지향 언어.
  • 클래스는 함수이며 기존 프로토타입 기반 패턴을 클래스 기반 패턴처럼 사용할 수 있도록 하는 문법적 설탕.

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

  1. 클래스를 new 연산자 없이 호출하면 에러가 발생한다. 하지만 생성자 함수를 new 연산자 없이 호출하면 일반 함수로서 호출된다.
  2. 클래스는 상속을 지원하는 extends와 super 키워드를 제공한다. 생성자 함수는 지원하지 않는다.
  3. 클래스는 호이스팅이 발생하지 않는 것처럼 동작한다. 하지만 함수 선언문으로 정의된 생성자 함수는 함수 호이스팅이, 함수 표현식으로 정의한 생성자 함수는 변수 호이스팅이 발생한다.
  4. 클래스 내의 모든 코드에는 암묵적으로 strict mode가 지정되어 실행. 하지만 생성자 함수는 암묵적으로 strict mode가 지정되지 않는다.

클래스를 표현식으로 정의할 수 있다는 것은 클래스가 값으로 사용될 수 있는 일급 객체라는 것을 의미한다.

일급 객체의 특징

  1. 무명의 리터럴로, 런타임에 생성 가능
  2. 변수나 자료구조에 저장 가능
  3. 함수의 매개변수에 전달 가능
  4. 함수의 반환 값으로 사용할 수 있다.

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

constructor

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

클래스 내에서 constructor를 생략하면 클래스에 빈 constructor가 암묵적으로 정의된다. constructor를 생략한 클래스는 빈 constructor에 의해 빈 객체를 생성한다.

정적 메서드

생성자 함수와 다르게, 클래스 몸체에서 정의한 메서드는 프로토타입 프로퍼티에 메서드를 추가하지 않아도 기본적으로 프로토타입 메서드가 되고 static 키워드를 붙이면 정적 메서드가 된다.

인스턴스를 생성하지 않아도 호출할 수 있는 메서드. 클래스 내에서 정적 메서드는 클래스에 바인딩된 메서드가 된다. 정적 메서드는 프로토타입 메서드와 달리 인스턴스로 호출하지 않고 클래스로 호출한다. 정적 메서드는 인스턴스로 호출할 수 없다.

정적 메서드와 프로토타입 메서드는 자신이 속해 있는 프로토타입 체인이 다르다.

정적 메서드는 클래스로 호출하고 프로토타입 메서드는 인스턴스로 호출한다.

정적 메서드는 인스턴스 프로퍼티를 참조할 수 없지만 프로토타입 메서드는 인스턴스 프로퍼티를 참조할 수 있다.

정적 메서드 내부의 this 는 인스턴스가 아닌 클래스를 가리킨다.

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

new 연산자와 함께 클래스를 호출하면 클래스 내부 메서드 [[Construct]]가 호출된다. 클래스는 new 연산자 없이 호출할 수 없다.

  1. 인스턴스 생성과 this 바인딩 : new 연산자와 함께 클래스를 호출하면 constructor 의 내부 코드가 실행되기에 앞서 암묵적으로 빈 객체가 생성된다. 이 빈 객체가 바로 클래스가 생성한 인스턴스다. 이때 클래스가 생성한 인스턴스의 프로토타입으로 클래스의 prototype 프로퍼티가 가리키는 객체가 설정된다. 그리고 인스턴스는 this에 바인딩 된다.
  2. 인스턴스 초기화 : constructor 의 내부 코드가 실행되어 this에 바인딩되어 있는 인스턴스를 초기화한다.
  3. 인스턴스 반환

프로퍼티

인스턴스 프로퍼티 : constructor 내부에서 정의. constructor 내부에서 this 에 추가한 프로퍼티는 언제나 클래스가 생성한 인스턴스의 프로퍼티가 된다. 인스턴스 프로퍼티는 언제나 public 하다.

접근자 프로퍼티 : 접근자 프로퍼티는 자체적으로는 값을 갖지 않고 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 사용하는 접근자 함수로 구성된 프로퍼티다.

getter 와 setter 이름은 인스턴스 프로퍼티처럼 사용된다. getter는 프로퍼티처럼 참조하는 형식으로 사용하며, 참조 시에 내부적으로 getter가 호출된다. setter도 프로퍼티처럼 값을 할당하는 형식으로 사용하며, 할당 시에 내부적으로 setter가 호출된다.

클래스 필드

클래스가 생성할 인스턴스의 프로퍼티.

자바스크립트의 클래스에서 인스턴스 프로퍼티를 선언하고 초기화하려면 반드시 constructor 내부에서 this에 프로퍼티를 추가해야 한다. 자바스크립트의 클래스 몸체에서는 메서드만 선언할 수 있다.

하지만 클래스 필드 정의 제안은 클래스 몸체에서 클래스 필드를 정의할 수 있게 해 준다. 클래스 몸체에서 클래스 필드를 정의하는 경우 this 에 클래스 필드를 바인딩 해서는 안된다. this는 클래스의 constructor와 메서드 내에서만 유효하다. 클래스 필드를 참조하는 경우 this를 반드시 사용해야 한다.

클래스 필드를 통해 메서드를 정의할 수도 있다. 클래스 필드에 함수를 할당하는 경우 함수는 프로토타입 메서드가 아닌 인스턴스 메서드가 된다. 모든 클래스 필드는 인스턴스 프로퍼티이기 때문이다.

private 필드 정의 제안

인스턴스 프로퍼티는 인스턴스를 통해 클래스 외부에서 언제나 참조할 수 있다. 언제나 public 이다. 클래스 필드도 기본적으로 public이기 때문에 외부에 그대로 노출된다. private 정의 제안이 되어있다. private 필드의 선두에 #를 붙여준다. 참조할 때도 마찬가지. private 필드는 클래스 내부에서만 참조할 수 있다. 인스턴스를 통한 접근, 자식 클래스 내부 접근이 불가능하다. 다만 접근자 프로퍼티를 통해 간접적으로는 접근할 수 있다.

private 필드는 반드시 클래스 몸체에 정의해야 한다. constructor 내부에 정의하면 에러가 발생한다.

static 필드 정의 제안

클래스에서는 static 키워드를 사용하여 정적 메서드를 정의할 수 있지만 static 키워드를 사용하여 정적 필드를 정의할 수는 없었다. 새로운 표준 사양이 제안되어 있다.

상속에 의한 클래스 확장

  • 기존 클래스를 상속받아 새로운 클래스를 확장하여 정의하는 것이다.
  • extends 키워드를 사용한다.
  • 수퍼클래스와 서브클래스는 인스턴스의 프로토타입 체인 뿐 아니라 클래스 간의 프로토타입 체인도 생성한다. 이를 통해 프로토타입 메서드, 정적 메서드 모두 상속이 가능하다.
  • super를 호출하면 수퍼클래스의 constructor를 호출한다. new 연산자와 함께 서브클래스를 호출하면서 전달한 인수는 모두 서브클래스에 암묵적으로 정의된 constructor의 super 호출을 통해 수퍼클래스의 constructor에 전달된다.

super 호출 시 주의 사항

  1. 서브 클래스에서 constructor를 생략하지 않는 경우 서브클래스의 constructor에서는 반드시 super를 호출해야 한다.
  2. 서브클래스의 constructor에서 super를 호출하기 전에는 this를 참조할 수 없다.
  3. super는 반드시 서브클래스의 constructor에서만 호출한다.

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

'Frontend > JavaScript' 카테고리의 다른 글

19. 배열  (1) 2023.12.21
18. 화살표 함수  (0) 2023.12.21
옵저버 패턴(Observer Pattern) 공부하기  (0) 2023.12.20
16. 클로저 Closure  (0) 2023.12.14
15. 실행 컨텍스트  (0) 2023.12.14