JavaScriptのstaticメソッド

javaScriptにはstaticメソッドを定義できます。
この中でthis.valiableを使った場合、どうなるかと言うメモです。

サンプルコード

とりあえすはサンプルコードです。
次の様なコードを考えます。

class Hoge {
	static get classMember(){
		return this.val1;
	}

	static set classMember(val){
		this.val1 = val;
	}

	get instanceMember(){
		return this.val1;
	}

	set instanceMember(val){
		this.val1 = val;
	}

	printClassMember(){
		document.write(`classMember1: ${Hoge.val1}<br>`);
	}

	printInstanceMember(){
		document.write(`classMember1: ${this.val1}<br>`);
	}
}

document.write("<span class='uline'>■const a = new Hoge();</span><br>")
const a = new Hoge();
a.printClassMember();
a.printInstanceMember();

document.write("<span class='uline'>■set classMember;</span><br>")
Hoge.classMember = 1;
a.printClassMember();
a.printInstanceMember();

document.write("<span class='uline'>■set instanceMember of a</span><br>")
a.instanceMember = "a";
a.printClassMember();
a.printInstanceMember();

document.write("<span class='uline'>■const b = new Hoge();</span><br>")
const b = new Hoge();
b.printClassMember();
b.printInstanceMember();

document.write("<span class='uline'>■set instanceMember of b</span><br>")
b.instanceMember = "b";
b.printClassMember();
b.printInstanceMember();

document.write("<span class='uline'>■print instance a</span><br>")
a.printClassMember();
a.printInstanceMember();

実行結果は次の通りです。

どう言うことか

コード中の「static get/set classMember()」と「get/set InstanceMember()」は共に「this.val1」を扱っています。
しかし、実行結果から「static get/set classMember()」と「get/set InstanceMember()」の「this.val1」は別物であることがわかります。

まず、最初に「const a = new Hoge();」の直後にそれぞれの「this.val」を印字した結果は共に「undefined」です。
まだ値を代入していないので当然です。

次にclassMemberに1を代入しています。
getter/setterはプロパティに見えるのでこの代入はsetter経由で「this.val1」への値の代入です。

続いてa.instanceMemberに"a"を代入しています。
これもgetter/setter経由で「this.val1」への代入ですが、classMemberの出力は前に代入した1のままです。
つまり、この時点でstaticメソッドとインスタンスメソッドの変数は同名でも別の変数であることがわかります。

続いて「const b = new Hoge();」してそれぞれの変数を印字しています。
classMemberの出力は1でクラスHogeに設定した値が出力されています。きちんとクラスに結びついていることが分かります。
対してinstanceMemberの出力はundefinedです。これも別のインスタンスなのでインスタンス変数はインスタンスごとにあると言う期待通りの動作です。

更に、インスタンスbのinstanceMemberに"b"を設定しました。
classMemberは1のまま、instanceMemberは"b"になっており期待通りです。
またこのとき、a.instanceMemberは影響を受けていません。これも期待通りです。

結論

staticメソッド内で使用されたthisはクラス自体を指します。
なのでstaticメソッド内で使用された変数「this.変数名」はクラス変数の様に扱われます。

インスタンスメソッド内で使用されたthisはインスタンスを指します。
なのでインスタンスメソッドで使用された「this.変数名」はインスタンス変数です。

ただし、インスタンスのメンバ変数はconstructorで宣言できますが、クラス変数はクラス内で宣言する構文がありません。
これは結構困ります。
次の記事で書きます。