프로토타입 기반의 객체 생성의 새로운 메커니즘
클래스는 생성자 함수보다 엄격하고 생성자 함수에서 제공하지 않는 기능도 제공
클래스 이름은 파스칼 케이스
class Person {} // 클래스 선언문, 가장 일반적
const Person = class {}; // 익명 클래스 표현식
const Person = class MyClass {}; // 기명 클래스 표현식
클래스를 표현식으로 정의할 수 있다 ? 클래스는 값으로 나타낼 수 있다
클래스는 함수이다
클래스 내부에는 constructor, 프로토타입 메서드, 정적 메서드 정의 가능
클래스는 함수로 평가되기 때문에 런타임 이전에 생성됨
클래스가 평가되어 생성된 함수 객체는 constructor이다 -> 생성자 함수로써 호출 가능
constructor는 함수 객체가 생성될 때 프로토타입도 같이 생성됨
클래스는 let, const 처럼 선언문 이전에 참조시 TDZ에 빠진다
클래스는 생성자 함수이다
new 연산자와 함께 호출하여 인스턴스 생성
생성자 함수를 new 없이 사용하면 일반 함수로 호출되지만 클래스는 에러
클래스 몸체에는 메서드만 정의할 수 있다
but 클래스 내부에 프로퍼티를 정의할 수있는 새로운 표준 사항 등장
인스턴스를 생성하고 처기화 하기 위한 특수한 메서드
class Person{
//생성자
constructor(name){
this.name = name;
}
}
const me = new Person('Sam');
constructor는 클래스 내에 1개만 존재 가능, 생략하면 constructor(){}
constructor 내부의 this는 앞으로 생성할 인스턴스를 가르킴
constructor 내부에는 반환문이 없어야 한다, 암묵적으로 인스턴스를 반환함
constructor는 메서드로 해석되지 않고 클래스가 평가되어 생성한 함수 객체 코드의 일부가 됨
즉 클래스 정의가 평가되면 constructor의 기술된 동작을 하는 함수 객체가 생성됨
클래스 내부에 정의한 메서드는 프로토타입 메서드이다
class Person{
//생성자
constructor(name){
this.name = name;
}
sayHi(){
console.log(`i am ${this.name}`);
}
}
const me = new Person('Sam');
me.say(); // i am Sam
메서드 선언할 때 static 키워드 붙이면 정적 메서드
class Person{
//생성자
constructor(name){
this.name = name;
}
static sayHi(){
console.log(`Hi`);
}
}
Person.sayHi(); 정적 메서드는 인스턴스 없이 바로 호출
const me = new Person('Sam');
me.sayHi(); // 에러, me의 프로토타입 체인에 sayHi()는 없다
클래스는 함수 객체로 평가되니까 자신의 프로퍼티(정적 메서드)를 갖는다
new 연산자와 함께 클래스는 호출하면 클래스의 내부 메서드 [[Construct]]가 호출되며 인스턴스 생성
인스턴스 프로퍼티는 constructor 내부에서 정의
클래스 필드 = 클래스가 생성할 인스턴스의 프로퍼티
ES2022 부터 클래스 필드 정의 구현
클래스 필드를 클래스 몸체에 정의 가능
class Person{
name = 'Sam'; // 초기값 없을 시 undefined
}
const me = new Person();
console.log(me); // Person {name:'Sam'}
인자를 받아서 값 세팅 해주려면 constructor 내부에서 해줘야한다
인스턴스 생성 시 인자로 세팅해줄 필요가 있으면 constructor 밖에 클래스 필드 선언하면 바보
class Person{
name;
constructor(name){
this.name = name; // 클래스 필드 참조할 때 this 필수
}
}
const me = new Person('Sam');
함수를 클래스 필드에 할당하면 인스턴스 메서드가 된다
모든 클래스 필드는 인스턴스의 프로퍼티가 되기 때문이다
클래스 필드에 함수 할당은 권장X
class Person{
getName = function(){
return this.name;
}
constructor(name){
this.name = name; // 클래스 필드 참조할 때 this 필수
}
}
const me = new Person('Sam');
me.getName(); // 'Sam'
원래는 private,public,protected 같은 접근 제한자를 지원하지 않지만
ES2022부터 가능
#을 붙여주면 됨, 참조할 때도 #
constructor 내부에 정의하면 에러남, 클래스 몸체에 정의해야 함
class Person{
#name = '';
constructor(name){
this.#name = name;
}
}
const me = new Person('Sam');
console.log(me.#name); // private필드는 클래스 내부에서만 참조 가능
ES2022부터
static 키워드로 정적 필드도 정의할 수 있다
class MyMath{
static PI = 3.14; // static public 필드 정의
static #num = 10; // static private 필드 정의
static increment(){ // static 메서드
return ++MyMath.#num;
}
}
console.log(MyMath.PI);
기존 클래스를 상속받아 새로운 클래스를 확장하여 정의
class Animal{
constructor(age,weight){
this.age = age;
this.weight = weight;
}
eat(){return 'eat';}
move(){return 'move';}
}
class Bird extends Animal{
fly(){return 'fly';}
}
const bird = new Bird(1,5);

수퍼클래스와 서브클래스 간의 상속 관계를 설정
클래스도 프로토타입을 통해 상속 관계를 구현

프로토타입 메서드와 함께 정적 메서드도 상속됨
extends 키워드는 [[Construct]] 내부 메서드를 갖는 함수 객체로 평가되는 모든 표현식을 상속받을 수 있음
서브 클래스에서 constructor를 생략하면 수퍼클래스의 constructor를 호출하는 코드가 암묵적으로 정의
constructor(...args){ super(...args);}
super()는 수퍼클래스의 constructor를 호출하여 인스턴스를 생성함
super는 호출할 수도 있고 식별자처럼 참조할 수도 있다
class Base{
constructor(a,b){
this.a = a;
this.b = b;
}
}
class Derived extends Base{
constructor(a,b,c){
super(a,b);
this.c = c;
}
}
const derived = new Derived(1,2,3);
console.log(derived); // Derived {a:1,b:2,c:3}
서브클래스의 메서드 내부에서 super를 참조하여 수퍼클래스의 메서드 호출 가능
super : super를 참조한 메서드를 갖고있는 객체의 프로토타입을 가르킴
class Base{
say(){return 'say';}
}
class Derived extends Base{
say(){
return super.say();
}
}
super는 Derived의 say 메서드에서 참조되고 있다
say 메서드는 Derived.prototype의 메서드이기때문에
Derived.prototype의 프로토타입인 Base.prototype을 가르킨다