Study JavaScript 0711 - 정적 메소드와 정적 프로퍼티

변승훈·2022년 7월 11일
0

Study JavaScript

목록 보기
42/43

정적 메서드와 정적 프로퍼티

property가 아닌 클래스 함수 자체에 메소드를 설정할 수도 있다.
이런 메소드를 "정적(static) 메소드"라고 부른다.

정적 메소드는 아래와 같이 클래스 안에서 static키워드를 붙여 만들 수 있다.

class User {
  static staticMethod() {
    console.log(this === User);
  }
}

User.staticMethod(); // true

정적 메소드는 메소드를 프로퍼티 형태로 직접 할당하는 것과 동일한 일을 한다.

class User { }

User.staticMethod = function() {
  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이 글 하나의 메소드가 아닌 클래스의 메소드여야 하는 이유가 여기에 있다.

이번에 살펴볼 예시는 ‘팩토리’ 메소드를 구현한 코드 예시다. 다양한 방법을 사용해 조건에 맞는 article 인스턴스를 만들어야 한다고 가정해 보자.

  1. 매개변수(title, date 등)를 이용해 관련 정보가 담긴 article 생성
  2. 오늘 날짜를 기반으로 비어있는 article 생성
  3. 기타 등등

첫 번째 방법은 생성자를 사용해 구현할 수 있다.
두 번째 방법은 클래스에 정적 메소드를 만들어 구현할 수 있습니다.

아래 Article.createTodays()의 예시처럼 가능하다.

class Article {
  constructor(title, date) {
    this.title = title;
    this.date = date;
  }

  static createTodays() {
    // this는 Article입니다.
    return new this("Today's digest", new Date());
  }
}

let article = Article.createTodays();

console.log( article.title ); // Today's digest

이제 Today’s digest라는 글이 필요할 때마다 Article.createTodays()를 호출하면 된다. 여기서도 마찬가지로 Article.createTodays()article의 메소드가 아닌 전체 클래스의 메소드이다.

정적 메소드는 아래 예시와 같이 항목 검색, 저장, 삭제 등을 수행해주는 데이터베이스 관련 클래스에도 사용된다.

// Article은 article을 관리해주는 특별 클래스라고 가정
// article 삭제에 쓰이는 정적 메서드
Article.remove({id: 12345});

정적 프로퍼티

정적 프로퍼티도 만들 수 있다. 정적 프로퍼티는 일반 클래스 프로퍼티와 유사하게 생겼는데 앞에 static이 붙는다는 점만 다르다.

class Article {
  static publisher = "Ilya Kantor";
}

console.log( Article.publisher ); // Ilya Kantor

위 예시는 Article에 프로퍼티를 직접 할당한 것과 동일하게 동작한다.

Article.publisher = "Ilya Kantor";

정적 프로퍼티와 메소드 상속

정적 프로퍼티와 메소드는 상속된다.

아래 예시에서 Animal.compareAnimal.planet은 상속되어서 각각 Rabbit.compareRabbit.planet에서 접근할 수 있다.

class Animal {
  static planet = "지구";

  constructor(name, speed) {
    this.speed = speed;
    this.name = name;
  }

  run(speed = 0) {
    this.speed += speed;
    console.log(`${this.name}가 속도 ${this.speed}로 달립니다.`);
  }

  static compare(animalA, animalB) {
    return animalA.speed - animalB.speed;
  }

}

// Animal을 상속받음
class Rabbit extends Animal {
  hide() {
    console.log(`${this.name}가 숨었습니다!`);
  }
}

let 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]] 참조를 만들어 낸다.

  1. 함수 Rabbit은 프로토타입을 통해 함수 Animal을 상속받는다.
  2. Rabbit.prototype은 프로토타입을 통해 Animal.prototype을 상속받는다.
    이런 과정이 있기 때문에 일반 메소드 상속과 정적 메소드 상속이 가능하다.

코드로 직접 확인해보자!

class Animal {}
class Rabbit extends Animal {}

// 정적 메소드
console.log(Rabbit.__proto__ === Animal); // true

// 일반 메소드
console.log(Rabbit.prototype.__proto__ === Animal.prototype); // true
profile
잘 할 수 있는 개발자가 되기 위하여

0개의 댓글