JS-22 정적 메서드 (23/01/11)

nazzzo·2023년 1월 11일
1

1. 정적 메서드


정적 메서드(Static Method)란 인스턴스를 생성하지 않아도 호출할 수 있는 함수를 말합니다
클래스에만 종속된 함수이며, 인스턴스에 상속되지 않습니다
즉 인스턴스로는 정적 메서드에 접근할 수 없습니다


아래는 사용 예제입니다

class myClass {
  // 함수명 앞에 static을 붙여서 정적 메서드를 생성할 수 있습니다
    static staticMethod() {
        console.log("이 친구는 정적 메서드");
    }
}
MyClass.staticMethod(); // "이 친구는 정적 메서드"

let instance = new MyClass();
instance.staticMethod(); // Uncaught TypeError: instance.staticMethod is not a function

함수 생성과 호출을 모두 클래스에서...


정적 메서드는 클래스 자체와 관련된 기능을 수행하지만
따로 인스턴스를 생성할 필요가 없을 경우에 사용합니다

예를 들어 우리가 지금까지 사용해온 Date.now() 또한 Date 클래스의 정적 메서드입니다
별 생각없이 써왔는데... 이런 이유때문에 인스턴스 생성 없이도 현재 시간을 호출할 수 있었던 거군요



2. 클래스 & this

정적 메서드와 동적 메서드는 this가 가리키는 대상이 달라질 수 있습니다

class Person {
    // #이 붙은 size는 private 속성이 됩니다
    // 특정 객체 정보를 console.log 등으로 드러내고싶지 않을 때 사용합니다
    #size = 100 
    constructor(_name, _age) {
      this.name = _name;
      this.age = _age;
    }
  
    // 동적 메서드
    getName() {
      return this.name
    }
  
    // 정적 메서드
    static getAge() {
      console.log(this)
    }

    static getNameByClass(){
    console.log(this.getName())
    }
}
  
  
  let person = new Person('Kim', 30);

console.log(person.getName()); // 'Kim'
Person.getAge(); //  class Person  

  • Person.getAge()는 정적 메서드이므로 클래스(Person)를 가리킵니다
  • person.getName()는 동적 메서드로 호출될 때 인스턴스(name과 age값을 가진 객체)를 가리킵니다
  • getNameByClass()에서는 this.getName() 형식으로 메서드를 호출하며,
    이렇게 정적 메서드를 통해 호출된 this는 클래스(Person)를 가리킵니다



3. 클래스 & super


아래 예제 코드에서 super.getName()this.getName()은 같은 기능을 하며,
양쪽 모두 "hello"를 반환합니다

하지만 각각이 가리키는 대상은 다릅니다


  class Person {
    constructor(_name, _age) {
      this.name = _name;
      this.age = _age;
    }

    static getName() {
      return "hello"
    }
  }

  class Man extends Person {
    constructor(_age) {
        super("Kim", _age)
    }

    static name () {
        console.log(super.getName()) // hello
        // super는 부모 클래스를 가리킵니다
        // prototype인 Person까지 거슬러올라 getName 함수를 찾아서 실행합니다

        console.log(this.getName()) // hello
        // this가 가리키는 대상은 Man
        // Pesrson 클래스에서 파생된 Man이 getName을 실행합니다
    }
  }
  
  const Kim = new Man(20)    
  console.log(Man.name())

  • super는 현재 클래스의 '부모 클래스'를 가리킵니다
    그래서 위 예제코드에서 super.getName()이 가리키는 대상은 Man이 아닌 Person 클래스입니다
    *super는 부모 클래스의 생성자를 호출하거나, 부모 클래스의 메서드에 접근할 때 사용합니다

  • 반면 console.log(this.getName())this는 현재 클래스인 Man을 가리킵니다
    정적 메서드는 인스턴스에는 상속되지 않지만 자식 클래스에는 상속되기 때문입니다



4. 정적 메서드 활용


직전 포스팅에서 define 메서드를 써서 만든 ORM 모델 생성함수를 클래스로 바꿔봅시다


[index]

const Sequelize = require("sequelize");
const config = require("../config");
const db = config.db[config.env];

const sequelize = new Sequelize(db.database, db.username, db.password, db);
// 소문자 sequelize는 인스턴스입니다

require("./comment.model")(sequelize, Sequelize);
// 인스턴스와 클래스를 인자로 모델 함수를 호출합니다

module.exports = {
  sequelize,
  Sequelize,
};

[comment.model]

module.exports = (sequelize, Sequelize) => {
    class Comment extends Sequelize.Model {
        static createTable() {
            return this.init ({
                // init은 define과 같은 기능을 하는 정적 메서드입니다
                // 두 가지 인자(테이블의 필드 정보, 옵션)를 받습니다
                userid: {
                    type: Sequelize.STRING(30),
                    allowNull: false,
                },
                content: {
                    type: Sequelize.TEXT(),
                    allowNull: false,
                }
            },
            {
                // init 메서드로 생성한 테이블 데이터를 아래 인스턴스에 전달해야 합니다
                sequelize: sequelize
            }
            )
        }
    }
    Comment.createTable() // 정적 메서드를 실행합니다
}

정리)

  • init은 Sequelize 클래스에 내장된 정적 메서드로 테이블을 생성하는 기능을 합니다
    정적 메서드는 클래스를 통해서만 상속이 이루어지기 때문에,
    자식 클래스인 Comment에서 이어받아 사용할 수 있습니다
    (즉 init 메서드는 인스턴스가 아닌 Comment 클래스에서 호출했다는 것!)
  • 두번째 인자로 전될된 sequelize(인스턴스)는 init을 통해 생성할 테이블 정보를 전달 받습니다
    그리고 임의로 만든 정적 메서드(createTable)을 호출하면 init 메서드도 따라서 호출됩니다

0개의 댓글