[JavaScript] 모던 자바스크립트 Deep Dive 25장 - 클래스
2022. 8. 9. 23:51ㆍWeb/JavaScript

클래스는 프로토타입의 문법적 설탕인가?
클래스와 생성자 함수의 몇 가지 차이
- 클래스를 new 연산자 없이 호출하면 에러가 발생한다. 하지만 생성자 함수를 new 연산자 없이 호출하면 일반 함수로서 호출된다.
- 클래스는 상속을 지원하는 extends와 super 키워드를 제공한다. 하지만 생성자 함수는 extend와 super 키워드를 지원하지 않는다.
- 클래스는 호이스팅이 발생하지 않는 것처럼 동작한다. 하지만 함수 선언문으로 정의된 생성자 함수는 함수 호이스팅이, 함수 표현식으로 정의한 생성자 함수는 변수 호이스팅이 발생한다.
- 클래스 내의 모든 코드에는 암묵적으로 strict mode가 지정되어 실행되며 strict mode를 해제할 수 없다. 하지만 생성자 함수는 암묵적으로 strict mode가 지정되지 않는다.
- 클래스의 constructor, 프로토타입 메서트, 정적 메서드는 모두 프로퍼티 어트리뷰트 [[Enumerable]]의 값이 false다. 다시 말해, 열거 되지 않는다.
클래스를 프로토타입 기반 객체 생서 패턴의 단순한 문법적 설탕이라고 보기보다는 새로운 객체 생성 메커니즘으로 보는 것이 좀 더 합당하다.
클래스 정의
클래스는 함수다. 따라서 클래스는 값처럼 사용할 수 있는 일급 객체다.
// 클래스 선언문
class Person{
// 생성자
constructor(name){
// 인스턴스 생성 및 초기화
this.name = name; // name 포로퍼티는 public하다.
}
// 프로토타입 메서드
sayHi(){
console.log(`Hi! My name is ${this.name}`);
}
// 정적 메서드
static sayHello(){
console.log('Hello!');
}
}
// 인스턴스 생성
const me = new Person('Eo');
// 인스턴스의 프로퍼티 참조
console.log(me.name); // Eo
// 프로토타입 메서드 호출
me.sayHi(); // Hi! My name is Eo
// 정적 메서드 호출
Person.sayHello(); // Hello!
클래스 호이스팅
클래스 선언문으로 정의한 클래스는 런타임 이전에 먼저 평가되어 함수 객체를 생성한다.
// 클래스 선언문
class Person{}
console.log(typeof Person); // function
클래스는 클래스 정의 이전에 참조할 수 없다.
console.log(typeof Person); // ReferenceError: Cannot access 'Person' before initialization
// 클래스 선언문
class Person{}
인스턴스 생성
클래스는 생성자 함수이며 new 연산자와 함께 호출되어 인스턴스를 생성한다.
클래스는 인스턴스를 생성하는 것이 유일한 존재 이유이므로 반드시 new 연산자와 함께 호출해야 한다.
class Person {}
// 인스턴스 생성
const me = new Person();
console.log(me); // person {}
메서드
클래스 몸체에는 0개 이상의 메서드만 선언할 수 있다. 클래스 몸체에서 정의할 수 있는 메서드는 constructor(생성자), 프로토타입 메서드, 정적 메서드의 세가지가 있다.
constructor
constructor는 인스턴스를 생성하고 초기화하기 위한 특수한 메서드다. 이름은 변경할 수 없다.
프로토타입 메서드
생성자 함수를 사용하여 인스턴스를 생성하는 경우 프로토타입 메서드를 생성하기 위해서는 명시적으로 프로토타입에 메서드를 추가해야 한다.
정적 메서드
정적 메서드는 인스턴스를 생성하지 않아도 호출할 수 있는 메서드를 말한다.
정적 메서드와 프로토타입 메서드의 차이
- 정적 메서드와 프로토타입 메서드는 자신이 속해 있는 프로토타입 체인이 다르다.
- 정적 메서드는 클래스로 호출하고 프로토타입 메서드는 인스턴스로 호출한다.
- 정적 메서드는 인스턴스 프로퍼티를 참조할 수 없지만 프로토타입 메서드는 인스턴스 프로퍼티를 참조할 수 있다.
클래스에서 정의한 메서드의 특징
- function 키워드를 생략한 메서드 축약 표현을 사용한다.
- 객체 리터럴과는 다르게 클래스에 메서드를 정의할 때는 콤마가 필요 없다.
- 암묵적으로 strict mode로 실행된다.
- for in 문이나 Object.keys 메서드 등으로 열거할 수 없다.
- new 연산자와 함께 호출할 수 없다.
클래스의 인스턴스 생성 과정
- 인스턴스 생성과 this 바인딩
- 인스턴스 초기화
- 인스턴스 반환
class Person{
// 생성자
constructor(name){
// 1. 암묵적으로 인스턴스가 생성되고 this에 바인딩된다.
console.log(this); // Person {}
console.log(Object.getPrototypeOf(this === Person.prototype)); // true
// 2. this에 바인딩되어 있는 인스턴스를 초기화한다.
this.name = name;
// 3. 완성된 인스턴스가 바인딩된 this가 암묵적으로 반환된다.
}
}
프로퍼티
- 인스턴스 프로퍼티: constructor 내부에서 정의해야 한다.
- 접근자 프로퍼티: 자체적으로 값을 갖지 않고 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 사용하는 접근자 함수로 구성된 프로퍼티다.
- 클래스 필드 정의 제안: 클래스 필드는 클래스 기반 객체지향 언어에서 클래스가 생성할 인스턴스의 프로퍼티를 가리키는 용어를 말한다. 클래스 몸체에서 클래스 필드를 정의하는 경우 this에 클래스 필드를 바인딩해서는 안된다. this는 클래스의 constructor와 메서드 내에서만 유효하다.
- private 필드 정의 제안: private 필드의 선두에는 #을 붙여준다. private 필드를 참조할 때도 #을 붙여주어야한다.
class Person{
// private 필드 정의
#name = '';
constructor(name){
// private 필드 참조
this.#name = name;
}
}
const me = new Person('Eo');
// private 필드 #name은 클래스 외부에서 참조할 수 없다.
console.log(me.#name); // SyntaxError: Private field '#name' must be declared in an enclosing class
- static 필드 정의 제안: static 키워드를 사용하여 정적 필드를 정의할 수 없없다. 현재 제안중
'Web > JavaScript' 카테고리의 다른 글
| [JavaScript] 모던 자바스크립트 Deep Dive 27장 - 배열 (0) | 2022.08.11 |
|---|---|
| [JavaScript] 모던 자바스크립트 Deep Dive 26장 - ES6 함수의 추가 기능 (0) | 2022.08.10 |
| [JavaScript] 모던 자바스크립트 Deep Dive 24장 - 클로저 (0) | 2022.08.08 |
| [JavaScript] 모던 자바스크립트 Deep Dive 23장 - 실행 컨텍스트 (0) | 2022.08.04 |
| [JavaScript] 모던 자바스크립트 Deep Dive 22장 - this (0) | 2022.08.04 |