notes
25장. 클래스
모던 JS Deep Dive — 클래스 문법·상속·캡슐화와 인스턴스 핵심 정리.
참고: 이웅모 《모던 자바스크립트 Deep Dive》 25장 · [MDN Classes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes)
class는 프로토타입의 문법적 설탕에 가깝되, 단순 설탕만은 아니다.
new 강제, 메서드 non-enumerable, extends/super, 호이스팅 TDZ, private 필드 등 안전장치·문법이 더해진 프로토타입 모델이다. 19·17을 알고 보면 class가 읽힌다.
flowchart TB
C[class Foo] --> CTOR[constructor / [[Construct]]]
C --> PROTO[Foo.prototype 메서드]
C --> STATIC[정적 메서드·필드]
SUB[class Bar extends Foo] --> SUPER[super / 체인 연결]
25.1 설탕인가?
본체는 프로토타입 위임. 다만 class는:
new없이 호출하면 TypeError- 본문 메서드는 보통 enumerable:false
extends가 체인·constructor 연결을 대신 정리- 클래스 선언은 let/const처럼 TDZ
“완전히 새로운 객체 모델”이 아니라 “실수하기 어려운 생성자+프로토타입”.
25.2 클래스 정의
class Person {
constructor(name) {
this.name = name;
}
sayHi() {
return `hi ${this.name}`;
}
static species() {
return 'homo';
}
}
const p = new Person('민섭');
console.log(p.sayHi(), Person.species());
console.log(Object.getPrototypeOf(p) === Person.prototype);
표현식도 가능: const C = class { … }.
25.3 클래스 호이스팅
선언은 호이스팅되나 TDZ. 선언 전 new Person은 ReferenceError.
함수 선언문처럼 끌어올려 바로 쓸 수 있다고 착각하지 말 것.
25.4 인스턴스 생성
new → 17과 같은 큰 그림(빈 객체, 프로토 연결, constructor 실행, return 규칙).
class constructor는 객체를 return하면 그 객체가 될 수 있으나, 원시 return은 무시되는 감각도 유사.
25.5 메서드
constructor
인스턴스 초기화. 하나. 생략 시 빈 constructor가 있는 것과 비슷. 서브클래스는 생략 시 super(...args)를 호출하는 기본형이 들어간다.
프로토타입 메서드
sayHi()는 Person.prototype에. 인스턴스마다 함수 복사 아님.
정적 메서드
static species는 Person 함수 객체에. 인스턴스에서 안 보임(19.12).
정적 vs 프로토타입
클래스 메서드 특징
축약 메서드 → non-constructor(화살표/new 불가한 쪽). strict. enumerable false인 경우가 일반적.
25.6 인스턴스 생성 과정 (복기)
- 새 객체,
[[Prototype]] = Person.prototype - constructor를 this=그 객체로 실행
- 필드 초기화(문법에 따라 순서 주의)
- 결과 반환
25.7 프로퍼티
인스턴스 프로퍼티
constructor 안 this.x = 또는 클래스 필드 x = 1.
접근자
get/set도 프로토타입에 정의 가능.
클래스 필드
class Counter {
n = 0;
inc = () => { this.n += 1; }; // 인스턴스 화살표 — this 고정, 공유 X
bump() { this.n += 1; } // 프로토타입 공유
}
private 필드
#n — 클래스 바깥에서 접근 SyntaxError/TypeError. 인스턴스별 은닉.
class Wallet {
#bal = 0;
deposit(n) { this.#bal += n; }
balance() { return this.#bal; }
}
static 필드
생성자 함수에 붙는 데이터. static #secret도 가능(환경 지원 시).
25.8 상속
extends
class Dog extends Animal — 프로토타입 체인 + 정적 체인까지 연결되는 그림.
constructor와 super
서브클래스 constructor에서 this 쓰기 전에 super(...) 필수.
class Animal {
constructor(name) { this.name = name; }
}
class Dog extends Animal {
constructor(name, breed) {
super(name);
this.breed = breed;
}
bark() { return 'wal'; }
}
super 키워드
- constructor 안: 부모 constructor
- 메서드 안: 부모 프로토타입 메서드 쪽 (
super.hello())
동적 상속
extends 뒤에 표현식 가능(extends mix(Base)). 고급 패턴.
예제
class Stack {
#items = [];
push(x) { this.#items.push(x); }
pop() { return this.#items.pop(); }
get size() { return this.#items.length; }
}
const s = new Stack();
s.push(1); s.push(2);
console.log(s.size, s.pop());
헷갈리던 장면 / 함정
- class를 완전히 다른 OOP로 오해
- 필드 화살표를 남발해 메모리·상속 테스트 깨짐
- super 전에 this
- private을 “진짜 보안”으로 착각 — 언어 수준 은닉일 뿐
- 호이스팅을 함수 선언과 동일시
표
질문 → 자답
Q. 생성자 함수를 버려도 되나? A. 새 코드는 class. 레거시·라이브러리·동작 이해는 프로토타입 모델 필요.
Q. 필드 vs constructor 할당? A. 필드는 선언이 한눈에. 무거운 초기화·조건은 constructor.
웹 보강 메모
MDN Classes·private fields·MDN super를 확인. 레포에서 prototype = 수동 상속을 extends로 옮길 후보를 표시.
실무로 바로
- 도메인 타입: class
- 공유 메서드: 프로토타입 메서드(일반 정의)
- 리스너 this: 필드 화살표 또는 bind
- 은닉:
#또는 모듈 스코프
new 없이 호출하면
class A {}
// A(); // TypeError: Class constructor A cannot be invoked without 'new'
생성자 함수 시절의 전역 오염 실수를 문법이 막는다(17·20).
프로토타입에 뭐가 붙나 확인
class Person {
say() {}
static all() {}
}
console.log(Object.getOwnPropertyNames(Person.prototype)); // constructor, say …
console.log(Object.getOwnPropertyNames(Person).includes('all')); // true
console.log(Object.keys(Person.prototype)); // [] 인 경우 많음 — enumerable false
믹스인 감각
const Speak = (Base) => class extends Base {
speak() { return '…'; }
};
class Dog extends Speak(class {}) {}
extends 표현식으로 동적 상속. 남용 시 체인 디버깅이 어려워진다.
실무 마이그레이션
- function Ctor + prototype → class
- 수동 Object.create 상속 → extends
- 클로저 은닉 → #field (또는 유지)
- 테스트: instanceof, 메서드 공유, new 없이 호출 실패
constructor return 규칙 복습
class A {
constructor() {
return { hijack: true };
}
}
console.log(new A()); // { hijack: true }
객체 return은 인스턴스를 교체할 수 있다. 실수든 팩토리 흉내든, 알고 쓸 것. 원시 return은 무시되고 원래 인스턴스가 남는다.
여기서 잠깐 💁♂️
26은 ES6 함수 변화(화살표·rest·파라미터 기본값). class 메서드·화살표 필드와 맞물린다.