はじめに
function Car() {
}
function Truck() {
}
Truck.prototype = new Car();
let t = new Truck();
プロトタイプ継承をこのように紹介している書籍をみてとても気持ち悪いを思った。
理屈は分かるし、アイデアとして面白いと思う。
しかし、継承に気を取られその他を破綻させてしまうやり方はどうにも受け入れが難い。
プロトタイプのconstructorを付け替えれば済む話かもしれないが、しなくて良いことをしないまま解決したい。
よりスマートな方法を探して、整理します。
盲点があればご指摘ください。
継承しなくても継承の考え方は必要
function Car() {
}
let car = new Car();
explicit prototype property(明示的なprototypeプロパティ)
コンストラクタ ⇒ プロトタイプ
この2つは常に対になって存在する
関数を定義すると、関数ごとにプロトタイプが作成される、ようだ。
implicit prototype link(暗黙のprototypeリンク)
インスタンス → プロトタイプ
※ 継承と呼ばれるのはこちら
組み合わせ一覧
下記の図は、インスタンスを中心に読んでいただきたい。
・インスタンスのコンストラクタは誰か?を意識する
・インスタンスはコンストラクタに紐づくプロトタイプをプロトタイプリンクを通じて継承する
※ ⇒ はexplicit prototype property、↑ はimplicit prototype linkを表す
実装編
class構文 + extendsを使用するとprototype linkの付け替えをうまくやってくれる
・サブクラスのプロトタイプはスーパークラスのプロトタイプをprototype linkで参照する
・サブクラスのコンストラクタはスーパークラスのコンストラクタをprototype linkで参照する
class構文 + extendsを使用しない場合は、prototype linkの付け替えを自分で行う必要がある。
どのように付け替えるのが適切か
Car.prototype → Object.prototypeはそのままでOK
Car → Function.prototypeはそのままで良いのか?
Car → Object → Function.prototypeとしたい。
function Car() {
}
Object.setPrototypeOf(Car, Object);
let car = new Car();
本題にもどります
function Car() {
}
Object.setPrototypeOf(Car, Object);
// Object.setPrototypeOf(Car.prototype, Object.prototype); // デフォルトと同じなので不要
function Truck() {
}
Object.setPrototypeOf(Truck, Car);
Object.setPrototypeOf(Truck.prototype, Car.prototype);
let t = new Truck();
babelの変換結果を見ると、もっと色々な操作が入っているので、まだまだ足りないことがあるのでしょう。
引き続き勉強します。
class Car {
}
class Truck extends Car {
}
let t = new Truck();
この糖衣構文の内部を完璧に理解することが目標です。