Stardew Dressup 개발일지(3)

Lybell·2022년 7월 13일
0

개발상황

현재 Stardew Dressup의 시트 데이터를 저장하는 store를 개조하는 중이다. 시트 데이터를 변환 후 리셋하는 기능을 추가하기 위해, default clothes data 변수를 추가하고, 부모 클래스에서 clothes data를 default clothes data로 할당하는 코드를 작성하는 과정에서 문제가 생겼다.

문제 상황

자세한 코드를 공개할 수는 없지만, 대충 이런 코드에서 오류가 생겼다.

class sheetDataStore
{
	_defaultClothesData = null;
	_clothesData = null;
	constructor()
	{
		this._clothesData = this._defaultClothesData;
    }
	...
}
class hatsDataStore extends sheetDataStore
{
	_defaultClothesData = someInitializedValue;
	constructor()
	{
		super();
      	const firstData = this._clothesData[0];
    }
	...
}

본래 나는 자식 클래스 필드에서 상속받은 _defaultClothesData 프로퍼티를 초기화시킨 뒤, super() 생성자에서 _clothesData_defaultClothesData로 초기화하고, 자식 생성자에서 _clothesData로 무언가를 하는 것을 기대하고 있었지만, 생성자 함수 내부의 _clothesData는 내부에서 null로 취급되는 것처럼 보였다.
그래서, 오늘은 클래스 필드로 선언한 변수의 동작 방식에 대해 알아보도록 하겠다.

오늘의 학습 내용

클래스 필드란?

class NoClassField
{
  constructor()
  {
    this.prop = 123; // this is property
  }
}

우리가 가장 잘 아는 ES6의 클래스 정의 방식을 가져왔다. c++ 등에서 클래스의 프로퍼티를 정의할 때와는 다르게, 자바스크립트에서는 생성자 함수 내부에 this.(프로퍼티명) = (초기값)의 형태로 프로퍼티를 정의한다.

class HasClassField
{
  prop = 123; // this is class field
}

이건 클래스 필드의 형태로 프로퍼티를 정의한 형태다. 보는 바와 같이, 클래스 블록 내부에 (프로퍼티명) = (초기값) 형태로 프로퍼티를 정의하는 문법을 클래스 필드라고 한다.

클래스 필드의 특징 중 하나로는, 메소드를 정의하는 것과 같이 클래스의 프로토타입에 프로퍼티가 정의되는 것이 아니라, 클래스의 개별 인스턴스에 프로퍼티가 정의된다는 것이다. 물론, 생성자 함수 내부에서 초기화된 프로퍼티 역시 클래스의 프로토타입이 아닌 개별 인스턴스에 프로퍼티가 정의되는지라, 클래스 필드만의 고유한 특징이라고 말할 수는 없다.

class MyClass
{
	propAsClassField = 12345;
	constructor()
	{
		this.propInConstructor = 56789;
    }
}
let myClass = new MyClass();
console.log(myClass.propAsClassField); // 12345
console.log(MyClass.prototype.propAsClassField); // undefined
console.log(myClass.propInConstructor); // 56789
console.log(MyClass.prototype.propInConstructor); // undefined

클래스 필드는 언제 초기화될까

class MyClass
{
	prop = 123;
	constructor()
	{
		console.log(this.prop); // ?
    }
}
let myClass = new MyClass();
console.log(myClass.newProp); // 123

다음의 코드를 실행했을 때 MyClass 생성자 안의 console.log에는 무엇이 출력될까?
출력 결과, 클래스 필드에서 초기화된 값인 123이 출력된다. 아마도 클래스 필드는 생성자를 호출하기 전에 초기화된 것으로 보인다.

그렇다면, 부모를 상속한 자식 클래스 필드는 언제 초기화될까?

class Parent
{
    defaultValue = 0;
	constructor()
	{
		console.log(`in parent:${this.defaultValue}`); // ?
	}
}
class Child extends Parent
{
	defaultValue = 123;
	constructor()
	{
		super();
        console.log(`in child:${this.defaultValue}`); // 123
	}
}
let test = new Child();

실험 결과, 부모 클래스의 생성자에서는 defaultValue가 자식 클래스의 것으로 취급되는 것이 아닌, 부모 클래스의 것으로 취급되는 것을 알 수 있었다.
즉, 자식 클래스 필드는 부모 클래스 필드의 생성자인 super()가 호출된 직후에 초기화된다는 것을 알 수 있었다.

profile
홍익인간이 되고 싶은 꿈꾸는 방랑자

0개의 댓글