자바스크립트 클래스에 static 메서드가 있다는 것은 다들 아실 겁니다. 그렇다면 static 메서드에서 this를 출력하면 무엇이 될까요?
class Test {
static getThis() {
return this;
}
}
console.log(Test.getThis()); // class Test
console.log(Test.getThis() === Test); // true
window나 undefined 같은 게 아니라 Test 클래스 그 자체가 나옵니다. 이 this는 Test 그 자체이므로 인스턴스의 this와 구분이 됩니다.
이번엔 다음과 같은 코드를 봅시다.
class Test {
static value = 'initial';
static getValue() {
return this.value;
}
static setValue(value) {
this.value = value;
}
static getThis() {
return this;
}
}
console.log(Test.value); // initial
Test.setValue('changed');
console.log(Test.getValue()); // changed
console.log(Test.value); // changed
console.log(Test.getThis()); // class Test { value: 'changed' }
Test.value = 'updated';
console.log(Test.getValue()); // updated
const t = new Test(); // 인스턴스 생성
t.value = 'instance'; // 인스턴스의 value 추가
console.log(Test.value); // 여전히 updated
console.log(t.value); // instance
static value는 Test.value로 접근 가능하고, static 메서드에서는 this가 Test이므로 this.value로 접근 가능합니다. 반대로 인스턴스 메서드에서는 this가 다르므로 Test.value로 접근해야 합니다.
싱글톤 클래스를 만들고 싶다면 그냥 클래스를 선언한 뒤 클래스에 static 속성과 static 메서드를 선언해도 될 것 같네요. 조금 응용하자면...
class Singleton {
static #instance;
constructor() {
if (!Singleton.#instance) {
Singleton.#instance = this;
}
return Singleton.#instance;
}
get() {
return Singleton.#instance;
}
static get() {
return this.#instance;
}
}
const a = new Singleton();
const b = new Singleton();
console.log(a.get() === b.get()); // true
console.log(a.get() === Singleton.get()); // true
console.log(Singleton.get() instanceof Singleton); // true
이렇게 하면 new로 호출하든 그냥 쓰든 모두 다 되는 싱글턴이 생성됩니다. static 메서드에서는 this를 쓰지만 인스턴스 메서드에서는 클래스명을 사용해야 서로 같은 걸 가리키게 됩니다.