기존 블로그에 작성한 내용을 velog로 이전한 글입니다
객체지향 언어의 class를 자바스크립트에서 사용하게 해주는 문법적 설탕이라고 할 수 있다.
하지만 클래스가 생성자 함수와 완전히 같지는 않다.
구분 | Class | 생성자 함수 |
---|---|---|
인스턴스 생성 | O | O |
super 호출 | O | X |
extends | O | X |
new 미사용 에러 | O | X |
암묵적 strict mode | O | X |
메소드[[Enumerable]] | X | O |
정의 방법과 인스턴스 생성 방법은 다음과 같다.
class Person {} // 클래스 선언문
const Person = class {}; // 익명 클래스 표현식
const Person = class MyClass {}; // 기명 클래스 표현식
const me = new Person(); // 인스턴스 생성
특징:
클래스는 함수로 평가되며 일급 객체이다.
클래스는 constructor
, static
, 프로토타입 메소드
를 쓸 수 있다.
let, const와 마찬가지로 호이스팅이 일어나지 않는 것처럼 보인다.
class Person {
// 생성자
constructor(name) {
// 인스턴스 생성 및 초기화
this.name = name;
}
}
인스턴스를 생성하고 초기화 할 때 쓰인다.
특징:
constructor는 클래스 내에 최대 한개만 쓸 수 있다. (어길시 SyntaxError 발생)
쓰지 않더라도 암묵적으로 빈 객체를 반환하게 consturctor를 사용한다.
return을 명시적으로 쓴다면 원시값은 무시, 객체는 반환한다.
class Person {
// 생성자
constructor(name) {
// 인스턴스 생성 및 초기화
this.name = name;
}
// 프로토타입 메소드
sayHi() {
console.log(`Hi! My name is ${this.name}`);
}
}
생성자 함수처럼 prototype
을 통해 명시하지 않아도 프로토타입 메소드가 된다.
class Person {
// 생성자
constructor(name) {
// 인스턴스 생성 및 초기화
this.name = name;
}
// 정적 메소드
static sayHi() {
console.log("Hi!");
}
}
인스턴스를 생성하지 않고 쓸 수 있는 메소드는 static
을 활용하여 정적 메소드로 활용하는 것이 좋다.
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
// fullName은 접근자 함수로 구성된 접근자 프로퍼티이다.
// getter 함수
get fullName() {
return this.firstName + " " + this.lastName;
}
// setter 함수
set fullName(name) {
[this.firstName, this.lastName] = name.split(" ");
}
}
생성자 함수와 마찬가지로 접근자 함수를 사용할 수 있다.
최신 사양의 브라우저(Chrome 74 이상)와 최신 Node.js(버전 12 이상)에서 private
한 변수를 사용할 수 있다.
class Person {
// private 필드 정의
#name = "";
constructor(name) {
// private 필드 참조
this.#name = name;
}
// name은 접근자 프로퍼티이다.
get name() {
// private 필드를 참조하여 trim한 다음 반환한다.
return this.#_name.trim();
}
}
static
메소드 이외에 static 필드
는 최신 사양의 브라우저(Chrome 74 이상)와 최신 Node.js(버전 12 이상)에서 사용할 수 있다.
class MyMath {
// static public 필드 정의
static PI = 22 / 7;
// static private 필드 정의
static #num = 10;
// static 메소드
static increment() {
return ++MyMath.#num;
}
}
클래스 필드에 변수 선언시 인스턴스 프로퍼티가 된다.
class Person {
// 클래스 필드에 선언시 최신 버전 nodejs나 브라우저에서 작동, 인스턴스 프로퍼티가 되지만 this를 이용한 초기화 불가
legend = "WooooW";
constructor(name, age) {
this.name = name;
this.age = age;
}
sayProfile() {
console.log(`이름: ${this.name}
나이: ${this.age}`);
}
}
const me = new Person("yu", 32);
console.log(Object.getOwnPropertyNames(me)); // [ 'legend', 'name', 'age' ]
console.log(Object.getOwnPropertyNames(Person)); // [ 'length', 'prototype', 'name' ]
생성자 함수와 달리 클래스는 다른 생성자 함수나 클래스를 상속 받아 확장할 수 있다.
extends
키워드extends
사용하여 클래스나 생성자 함수를 상속받을 수 있다.
단 좌항에는 반드시 클래스가 와야 한다.
extends
는 [[Construct]] 내부 메소드를 갖는 함수 객체를 반환하는 표현식을 사용할 수 있다.
function Base1() {}
class Base2 {}
let condition = true;
// 조건에 따라 동적으로 상속 대상을 결정하는 서브 클래스
class Derived extends (condition ? Base1 : Base2) {}
super
키워드호출시(super()
) : 수퍼 클래스(상위 클래스)의 constructor 실행
반드시 constructor 안에서 호출해야 한다.
참조시 : 수퍼 클래스(상위 클래스)의 메소드 사용
축약 표현된 메소드 안에서면 super
참조 사용이 가능하다
class Person {
// 클래스 필드에 선언시 최신 버전 nodejs나 브라우저에서 작동, 인스턴스 프로퍼티가 되지만 this를 이용한 초기화 불가
legend = "WooooW";
constructor(name, age) {
this.name = name;
this.age = age;
}
sayProfile() {
console.log(`이름: ${this.name}
나이: ${this.age}`);
}
}
class Man extends Person {
constructor(name, age, hp, mp) {
super(name, age); // 반드시 super 호출로 상위 클래스 초기화를 마쳐야함
this.hp = hp;
this.mp = mp;
}
goGym() {
console.log("운동하느라 체력이 감소했다", this.hp, "-->", --this.hp);
}
}
const me = new Man("Yu", 32, 200, 200);
console.log(me); // Man { legend: 'WooooW', name: 'Yu', age: 32, hp: 200, mp: 200 }
me.goGym(); // 운동하느라 체력이 감소했다 200 --> 199
me.goGym(); // 운동하느라 체력이 감소했다 199 --> 198
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
static sayProfile() {
console.log(`super의 정적 메소드`);
}
}
class Man extends Person {
static sayProf() {
super.sayProfile();
}
}
Man.sayProf(); // super의 정적 메소드