JavaScriptのクラスのプロパティ

前の記事で無理やりクラス変数を定義する方法を紹介しました。
そんなことをしなくても同様のことはstaticなgetter/setterでできます。
staticなメソッドの記事を書きながら何でこんなことを頑張ったのか orz

サンプルコード

単なるstaticなgetter/setterの例です。

HogeTag.html

class Hoge(){
	static set property1(val){
		this.prop1 = val;
	}

	static get property1(){
		return this.prop1;
	}
}

staticなメソッドの記事でも出てきました。
staticメソッドの中のthis.変数のthisはクラスを指すのでこれはクラス変数として機能します。

static initializer

前の記事で一番やりたかったことはクラスを定義した時点で動的にクラス変数の値を設定するということです。
これはstaticなsetterでもできます(当たり前orz)。

<div id="HogeTarget">ホゲホゲ</div>
<script>
class Hoge {
	static set testStr(val){
		this.test_str = val;
	}

	static get testStr(){
		return this.test_str;
	}

	get testStr(){
		return Hoge.testStr;
	}
}

Hoge.testStr = document.getElementById("HogeTarget").textContent.trim();

document.write(`Hoge.testStr: ${Hoge.testStr}<br>`);
const a = new Hoge();
document.write(`a.testStr: ${a.testStr}<br>`);
</script>

実行結果以下です。

ホゲホゲ

きちんとクラス変数として使えています。
クラス定義の後、インスタンスをnewする前にクラスのプロパティをセットしてやればstatic initializer的なことも問題ありません。

それから、何となくきちんと動くんじゃないかとは思っていましたが、staticなメソッドとインスタンスメソッドは同名でも問題ないですね。きちんと別物として扱われています。

しかし、行儀が悪いとしてもJavaScript的に問題がないなら前の記事の様にやったほうが楽じゃないか? という意見があるかもしれません。

write onceなプロパティ

前の記事では重要な点を妥協しています。
それが、クラス構築時に値をセットしたらそれ以降は変更できないという機能を実現することです。
クラスのプロパティを使うとこれは簡単に実現できます。

<div id="FugaTarget">ふがふが</div>
<script>
class Fuga {
	static set testStr(val){
		if(!this.test_str){this.test_str = val;}
	}

	static get testStr(){
		return this.test_str;
	}

	get testStr(){
		return Fuga.testStr;
	}
}

Fuga.testStr = document.getElementById("FugaTarget").textContent.trim();

document.write(`Fuga.testStr (before reset): ${Fuga.testStr}<br>`);

Fuga.testStr = "Other String";
document.write(`Fuga.testStr (after reset): ${Fuga.testStr}
`); const b = new Fuga(); document.write(`b.testStr: ${b.testStr}<br>`); </script>

実行結果です。

ふがふが

setterで「if(!this.test_str){this.test_str = val;}」とすることで、1回値が設定されたら二度と変更できない様にしています。
実行結果からもきちんと機能していることが確認できます。

つまり、次の様にすることでJavaのクラス変数+static initializer的なことが完全に実現できます。
  • staticなgetter/setterを作る
  • setterはwrite onceの仕組みを入れる
  • クラス定義直後にプロパティをセットする

結論

前の記事の様な行儀の悪いことはせず、staticなgetter/setterを使いましょう。