ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Javascript] 클래스의 정적(static)메소드와 프로퍼티, 상속
    Language/JavaScript 2023. 1. 3. 23:09

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

    ES6 클래스에서 static 키워드는 클래스의 정적(static)메소드를 정의한다. 정적 메소드는 클래스의 인스턴스가 아닌 클래스의 이름으로 호출한다. 따라서 클래스의 인스턴스를 생성하지 않아도 호출할 수 있다.

    class Foo {
      constructor(prop) {
        this.prop = prop;
      }
    
      static staticMethod() {
        /*
        정적 메소드 내부에서 this는 클래스의 인스턴스가 아닌 클래스 자신을 가리킨다.
        */
        return 'staticMethod';
      }
    
      prototypeMethod() {
        return this.prop;
      }
    }
    
    // 정적 메소드는 클래스 이름으로 호출한다.
    console.log(Foo.staticMethod());
    
    const foo = new Foo(123);
    // 정적 메소드는 인스턴스로 호출할 수 없다.
    console.log(foo.staticMethod()); // Uncaught TypeError: foo.staticMethod is not a function
    

    또한 클래스 프로퍼티에도 사용할 수 있다. 정적 메소드와 마찬가지로 정적 클래스 프로퍼티는 인스턴스가 아닌 클래스의 이름으로 호출하며 클래스의 인스턴스를 생성하지 않아도 호출할 수 있다.

    class Foo {
      // 생성된 인스턴스의 갯수
      static instanceCounter = 0;
      constructor() {
        // 생성자가 호출될 때마다 카운터를 1씩 증가시킨다.
        Foo.instanceCounter++;
      }
    }
    
    var foo1 = new Foo();
    var foo2 = new Foo();
    
    console.log(Foo.instanceCounter);  // 2
    console.log(foo2.instanceCounter); // error TS2339: Property 'instanceCounter' does not exist on type 'Foo'.
    

     

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

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

    아래 예시에서 Animal.compare와 Animal.planet은 상속되어서 각각 Rabbit.compare와 Rabbit.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]] 참조를 만들어낸다.

    1. 함수 Rabbit은 프로토타입을 통해 함수 Animal을 상속받는다.

    2. Rabbit.prototype은 프로토타입을 통해 Animal.prototype을 상속받는다.

     

    이런 과정이 있기 때문에 일반 메서드 상속과 정적 메서드 상속이 가능하다.

    class Animal {}
    class Rabbit extends Animal {}
    
    // 정적 메서드
    alert(Rabbit.__proto__ === Animal); // true
    
    // 일반 메서드
    alert(Rabbit.prototype.__proto__ === Animal.prototype); // true

    댓글