6時だョ!!全員集合!!

Rails・JavaScrictを中心にアウトプットします。

2022年1月6日 JavaScript (JS Primer) クラスのプロトタイプメソッドの定義

  • クラスの動作はメソッドによって定義できます。
  • class構文ではクラスに対して自由にメソッドを定義できます。
  • このクラスに定義したメソッドは作成したインスタンスが持つ動作となります。
  • メソッドでクラスのインスタンスを参照するには、thisを使います。 new演算子で生成したインスタンスオブジェクトがベースオブジェクト、つまり『this』となります。

クラス構文の中で定義したthisインスタンス変数を指す。 とシンプルに覚えてもいいかも知れません。

class クラス {
    メソッド() {
        // ここでの`this`はベースオブジェクトを参照
    }
}
const インスタンス = new クラス();
インスタンス.メソッド(); // メソッドの呼び出し

クラスのプロトタイプメソッド定義では、オブジェクトにおけるメソッドとは異なりkey : valueのように:区切りでメソッドを定義できないことに注意してください。 つまり、次のような書き方は構文エラー(SyntaxError)となります。

  • メソッドの短縮記法以外はSyntaxErrorとなるそうです。
  • クラス構文で定義するプロトタイプメソッドはメソッドの短縮記法で書く必要がある。 と覚えておくと良いかも知れません。
class クラス {
   // SyntaxError
   メソッド: () => {}
   // SyntaxError
   メソッド: function(){}
}

このようにクラスに対して定義したメソッドは、クラスの各インスタンスから共有されるメソッドとなります。 このインスタンス間で共有されるメソッドのことをプロトタイプメソッドと呼びます。 また、プロトタイプメソッドはインスタンスから呼び出せるメソッドであるためインスタンスメソッドとも呼ばれます。

以下のコード例ではCounterクラスにincrementメソッドを定義しています。 Counterクラスのインスタンスはそれぞれ別々の状態(countプロパティ)を持ちます。

class Counter {
    constructor() {
        this.count = 0;
    }
    increment() {
        this.count++;
    }
}
const counterA = new Counter();
const counterB = new Counter();
// `counterA.increment()`のベースオブジェクトは`counterA`インスタンス
counterA.increment();
// 各インスタンスの持つプロパティ(状態)は異なる
console.log(counterA.count); // => 1
console.log(counterB.count); // => 0
  • ++ がインクリメント演算子と呼ぶので、ここではプロトタイプメソッド名としてincrement命名されています。このようにメソッド名からどんな動作をするメソッドかを理解できるものにする事はとても重要です。

インスタンス間でのメソッドの共有

プロトタイプメソッドは各インスタンス間で共有されます。 既存のプロトタイプメソッドを例に検証してみました。 以下が検証したコード例です。

console.log(Object.toString);
console.log(Array.toString);

console.log(Object.toString === Array.toString);

出力結果
function toString() { [native code] }
function toString() { [native code] }
true

生成されるインスタンスのプロトタイプメソッドが一致していることが確認出来ました。

参考

クラスのプロトタイプメソッドの定義