prototype이 아닌 클래스 자체에 메서드를 설정할 수도 있다. 이런 메서드를 정적(static) 메서드라고 부른다.
정적 메서드는 아래와 같이 클래스 안에서 static 키워드를 붙여 만들 수 있다.
class User {
static staticMethod() {
console.log(this === User);
}
}
User.staticMethod(); // true
User.staticMethod()가 호출될 때 this의 값은 클래스 생성자인 User가 된다.
정적 메서드는 어떤 특정한 객체가 아닌 클래스에 속한 함수를 구현하고자 할 때 주로 사용된다.
객체 Article이 여러 개 있고 이들을 비교해줄 함수가 필요하다고 가정해보자. 가장 먼저 아래와 같이 Article.compare를 추가하는 방법이 떠오를 것이다.
class Article {
constructor(title, date) {
this.title = title;
this.date = date;
}
static compare(articleA, articleB) {
return articleA.date - articleB.date;
}
}
// 사용법
let articles = [
new Article("HTML", new Date(2019, 1, 1)),
new Article("CSS", new Date(2019, 0, 1)),
new Article("JavaScript", new Date(2019, 11, 1)),
];
articles.sort(Article.compare);
console.log(articles[0].title); // CSS
여기서 Article.compare는 article을 비교해주는 수단으로, 글 전체를 내림차순으로 비교를 수행한다. Article.compare이 글 하나의 메서드가 아닌 클래스의 메서드(정적 메서드)여야 하는 이유가 여기에 있다.
정적 프로퍼티는 일반 클래스 프로퍼티와 유사하게 생겼지만 앞에 static이 붙는다.
class Article {
static publisher = "Ilya Kantor";
}
console.log(Article.publisher); // Ilya Kantor
정적 프로퍼티와 메서드는 상속된다.
아래 Animal.compare와 Animal.planet은 상속되어서 각각 Rabbit.compare와 Rabbit.planet에 접근할 수 있다.
class Animal {
static planet = "지구";
constructor(name, speed) {
this.name = name;
this.speed = speed;
}
run(speed = 0) {
this.speed += speed;
console.log(`${this.name}가 속도 ${this.speed}로 달립니다.`);
}
static compare(animalA, animalB) {
return animalA.speed - animalB.speed;
}
}
class Rabbit extends Animal {
hide() {
console.log(`${this.name}가 숨었습니다!`);
}
}
const rabbits = [new Rabbit("흰 토끼", 10), new Rabbit("검은 토끼", 5)];
rabbits.sort(Rabbit.compare);
rabbits[0].run(); // 검은 토끼가 속도 5로 달립니다.
console.log(Rabbit.planet); // 지구
Rabbit.compare을 호출하면 Animal.compare가 호출된다.
이게 가능한 이유는 프로토타입 때문이다. extends 키워드는 Rabbit의 [[Prototype]]이 Animal을 참조하도록 해준다.
따라서 Rabbit extends Animal은 두 개의 [[Prototype]] 참조를 만들어 낸다.
Rabbit은 프로토타입을 통해 함수 Animal을 상속받는다.Rabbit.prototype은 프로토타입을 통해 Animal.prototype을 상속받는다.이러한 과정이 있기 때문에 일반 메서드 상속과 정적 메소드 상속이 가능하다.
정적 메서드, 정적 프로퍼티는 특정 클래스의 인스턴스가 아닌, 즉 특정 인스턴스와 상관없이 애플리케이션 전역에서 사용할 메서드, 프로퍼티를 만들 때 사용한다.
이는 this를 사용하지 않는 메서드, 프로퍼티는 정적 메서드, 프로퍼티로 정의할 수 있다는 말과 같다.
Reference