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

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

2022年1月24日 JavaScript (JS Primer)静的メソッドの継承

【復習-1】

// プロパティを持たない空のオブジェクトを作成
// = `Object`からインスタンスオブジェクトを作成
const obj = new Object();
console.log(obj); // => {}

// 上記と以下は同義です。
const obj = {}

【復習2】 静的メソッド

静的メソッドはクラスをインスタンス化せずに利用できます。

class クラス {
    static メソッド() {
        // 静的メソッドの処理
    }
}
// 静的メソッドの呼び出し
クラス.メソッド();

静的メソッドの継承

継承を行うと、静的メソッドも継承されます。

class Parent {
    static hello() {
        return "Hello";
    }
}
class Child extends Parent {}
console.log(Child.hello()); // => "Hello"

extendsによって継承した場合、子クラスのコンストラクタのPrototype内部プロパティには親クラスのコンストラクタが設定されます。 このコードでは、ChildコンストラクタのPrototype内部プロパティにParentコンストラクタが設定されます。

Child.helloプロパティを参照した場合には、次のような順番でオブジェクトを探索しています。

1. Childコンストラク
2. Parentコンストラクタ(ChildコンストラクタのPrototypeの参照先)

クラスのコンストラクタ同士にもプロトタイプチェーンの仕組みがあるため、子クラスは親クラスの静的メソッドを呼び出せます。

ここで確認をしてみます。

class Parent {
    static hello() {
        return "Hello";
    }
}
class Child extends Parent {}
const yano = new Child();
console.log(yano);

上記のように定義したインスタンスオブジェクトを出力してみると以下のようになります。

superプロパティ

子クラスから親クラスのコンストラクタ処理を呼び出すにはsuper()を使います。 同じように、子クラスのプロトタイプメソッドからは、super.プロパティ名で親クラスのプロトタイプメソッドを参照できます。

次のコードでは、Child#methodの中でsuper.method()と書くことでParent#methodを呼び出しています。 このように、子クラスから継承元の親クラスのプロトタイプメソッドはsuper.プロパティ名で参照できます。

class Parent {
    method() {
        console.log("Parent#method");
    }
}
class Child extends Parent {
    method() {
        console.log("Child#method");
        // `this.method()`だと自分(`this`)のmethodを呼び出して無限ループする
        // そのため明示的に`super.method()`とParent#methodを呼び出す
        super.method();
    }
}
const child = new Child();
child.method();
// コンソールには次のように出力される
// "Child#method"
// "Parent#method"

Child#methodはChild.prototype.methodと同じ意味でしたね。

このコードではChild#methodが定義されているため、child.methodはChild#methodを呼び出します。 そしてChild#methodはsuper.methodを呼び出しているため、Parent#methodが呼び出されます。

静的メソッドの例

クラスの静的メソッド同士も同じようにsuper.method()と書くことで呼び出せます。 次のコードでは、Parentを継承したChildから親クラスの静的メソッドを呼び出しています。

class Parent {
    static method() {
        console.log("Parent.method");
    }
}
class Child extends Parent {
    static method() {
        console.log("Child.method");
        // `super.method()`で`Parent.method`を呼びだす
        super.method();
    }
}
Child.method();
// コンソールには次のように出力される
// "Child.method"
// "Parent.method"

継承の判定

あるクラスが指定したクラスをプロトタイプ継承しているかはinstanceof演算子を使って判定できます。

次のコードでは、ChildのインスタンスはChildクラスとParentクラスを継承したオブジェクトであることを確認しています。

class Parent {}
class Child extends Parent {}

const parent = new Parent();
const child = new Child();
// `Parent`のインスタンスは`Parent`のみを継承したインスタンス
console.log(parent instanceof Parent); // => true
console.log(parent instanceof Child); // => false
// `Child`のインスタンスは`Child`と`Parent`を継承したインスタンス
console.log(child instanceof Parent); // => true
console.log(child instanceof Child); // => true

上記のコードを日本語で言い換えると以下のようになります。

親クラスを継承した子クラス"child"の場合

親クラスで定義したものを継承した子クラスから呼び出すことは可能だという認識を持ちました。 その方法や仕組みについて学べました。

参考

JS primer 静的メソッドの継承