클래스는 객체를 생성하는 일종의 템플릿이다. 클래스는 데이터를 압축한다. 자바스크립트의 클래스는 prototype에 기반하지만, ES5의 클래스 같은 시맨틱과 공유되지 않는 문법과 시맨틱을 가진다.
함수 표현식과 함수 선언식을 선언하는 것처럼 클래스는 사실 '특별한 함수'로, 클래스 신택스는 클래스 표현식과 클래스 선언식 두 컴포넌트를 가진다.
클래스를 정의하는 한 가지 방법은 클래스 선언식이다. 클래스를 정의하기 위해서는 클래스의 이름과 함께 class
키워드를 사용한다. 아래의 예시에서는 Rectangle
이 된다.
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
함수 선언식(function declarations)과 클래스 선언식(class declaration) 사이의 중요한 차이점은 함수 선언식이 호이스팅되고, 클래스 선언식은 그렇지 못한다는 점이다. 우선 클래스를 선언한 뒤 그 후에 접근해야 한다. 그렇지 않으면 아래 같은 코드를 ReferenceError를 출력할 것이다.
const p = new Rectangle(); // Reference Error
class Rectangle {}
클래스를 정의하는 또 다른 방법이다. 클래스 표현식은 이름 붙여지거나, 익명으로 만들어질 수도 있다. named 클래스 표현식에 붙여진 이름은 클래스 바디에 지역적이다. (클래스의 name
속성을 통해 검색될 수는 있다. 인스턴스의 name
속성에 의해서는 불가능하다)
// unnamed
let Rectangle = class {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
console.log(Rectangle.name); // Rectangle
// named
let Rectangle = class Rectangle2 {
constructor(height, width) {
this.height = height;
this.width = width;
}
};
console.log(Rectangle.name); // Rectangle2
클래스 표현식도 마찬가지로 호이스팅 규칙에 적용받는다. 우선 선언한 뒤에 접근해야 한다.
클래스 바디는 {}
로 감싸진 부분을 말한다. 이 부분은 메소드와 constructor 같은 클래스 멤버를 정의하는 부분이다.
클래스 바디는 엄격 모드 안에서 실행된다.
constructor 메서드는 class 키워드로 생성된 객체의 생성과 초기화를 위한 특별한 메서드이다. 하나의 클래스 안에는 constructor라는 이름을 가진 특별한 메서드는 오직 하나만 올 수 있다. 하나 이상의 constructor 메서드가 온다면 SyntaxError를 출력할 것이다.
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
// getter
get area() {
return this.calcArea();
}
// method
calcArea() {
return this.height * this.width;
}
}
const square = new Rectangle(10, 10);
console.log(square.area); // 100
class Polygon {
constructor(...sides) {
this.sides = sides;
}
// method
getSides() {
for(const side of this.sides) {
yield side;
}
}
}
const pentagon = new Polygon(1, 2, 3, 4, 5);
console.log([...pentagon.getSides()]); // [1, 2, 3, 4, 5]
static
키워드는 클래스의 static method와 static property를 정의한다. Static 멤버는 이 클래스를 인스턴스화(instantiating)하지 않고 호출된며, 클래스 인스턴스를 통해 호출하는 것이 불가능하다. Static methods는 종종 애플리케이션을 위한 유틸리티 함수를 생성하기 위해 쓰이며, Static properties는 캐시나 fixed-configuration, 또는 인스턴스 전체에 복사될 필요가 없는 다른 데이터를 위해 유용하게 쓰인다.
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
static displayName = 'Point';
static distance(a, b) {
const dx = a.x - b.x;
const dy = a.y - b.y;
return Math.hypot(dx, dy)
}
}
const p1 = new Point(5, 5);
const p2 = new Point(10, 10);
p1.displayName; // undefined
p1.distance; // undefined
p2.displayName; // undefined
p2.distance; // undefined
console.log(Point.displayName); // 'Point'
console.log(Point.distance(p1, p2)); // 7.0710678118654755
this
를 바인딩하기가령 변수에 메서드를 할당하고 이를 부르는 것처럼, static 또는 프로토타입 메서드를 this 를 위한 value 없이 호출했을 때, this
값은 메서드 내에서 undefined
일 것이다. 'use strict' 구문이 없어도 같은 반응이 나온다. class 바디는 항상 엄격 모드 내에서 실행되기 때문이다.
class Animal {
speak() {
return this;
}
static eat() {
return this;
}
}
let obj = new Animal();
obj.speak(); // the Animal object
let speak = obj.speak;
speak(); // undefined
Animal.eat(); // class Animal
let eat = Animal.eat;
eat(); // undefined