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

RHUK2·2022년 5월 6일
0

Javascript

목록 보기
43/56

📚 Reference


javascript.info, https://ko.javascript.info/static-properties-methods

참고 사이트에 내용을 개인적으로 복습하기 편하도록 재구성한 글입니다.
자세한 설명은 참고 사이트를 살펴보시기 바랍니다.


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


"prototype"이 아닌 클래스 함수 자체에 메서드를 설정할 수도 있습니다. 이런 메서드를 정적(static) 메서드라고 부릅니다.

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

class User {
  static staticMethod() {
    alert(this === User);
  }
}

User.staticMethod(); // true

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

class User { }

User.staticMethod = function() {
  alert(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);

alert( articles[0].title ); // CSS

여기서 Article.compare는 article(글)을 비교해주는 수단으로, 글 전체를 "위에서" 바라보며 비교를 수행합니다. Article.compare이 글 하나의 메서드가 아닌 클래스의 메서드여야 하는 이유가 여기에 있습니다.

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

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

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

아래 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();

alert( 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";
}

alert( 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;
    alert(`${this.name}가 속도 ${this.speed}로 달립니다.`);
  }

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

}

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

let rabbits = [
  new Rabbit("흰 토끼", 10),
  new Rabbit("검은 토끼", 5)
];

rabbits.sort(Rabbit.compare);

rabbits[0].run(); // 검은 토끼가 속도 5로 달립니다.

alert(Rabbit.planet); // 지구

이제 Rabbit.compare을 호출하면 Animal.compare가 호출됩니다.

이게 가능한 이유는 프로토타입 때문입니다. 이미 예상하셨겠지만, extends 키워드는 Rabbit[[Prototype]]Animal을 참조하도록 해줍니다.

따라서 Rabbit extends Animal은 두 개의 [[Prototype]] 참조를 만들어 냅니다.

함수 Rabbit은 프로토타입을 통해 함수 Animal을 상속받습니다.
Rabbit.prototype은 프로토타입을 통해 Animal.prototype을 상속받습니다.
이런 과정이 있기 때문에 일반 메서드 상속과 정적 메서드 상속이 가능합니다.

class Animal {}
class Rabbit extends Animal {}

// 정적 메서드
alert(Rabbit.__proto__ === Animal); // true

// 일반 메서드
alert(Rabbit.prototype.__proto__ === Animal.prototype); // true
profile
생각 많이 하지 않기 😎

0개의 댓글