次のコードが気になります。
//subclass extends superclass
Rectangle.prototype = new Shape();
これは一般的なパターンですが、プロトタイプの作成とインスタンスの初期化Shape
の両方を使用しているため、あまり良いパターンではありません。どちらかを行う必要があります。(たとえば、引数を与える必要がある場合はどうするか考えてみてください。どのような引数を使用して を作成しますか?)Shape
Rectangle.prototype
しかし、どちらも必要ありませんRectangle.prototype = Shape.prototype
。なぜなら、物事を追加することができないからですRectangle.prototype
(同じオブジェクトを指しているので、それらをインスタンスにもShape.prototype
追加します)。Shape
したがって、doを介して作成されたオブジェクトと同じようにShape.prototype
、プロトタイプとして を使用する (たとえば、 を継承する)新しいオブジェクトを作成する必要がありますが、作成するための呼び出しは必要ありません。そして、その新しいオブジェクトを として使用します。Shape.prototype
new Shape
Shape
Rectangle.prototype
ECMAScript5 の時点で、次を使用してそれを行うことができますObject.create
。
Rectangle.prototype = Object.create(Shape.prototype);
Object.create
新しいオブジェクトを作成し、最初の引数をオブジェクトの基になるプロトタイプとして割り当てます。
厳密には必要ではありませんが、それを行った後、constructor
新しいオブジェクトにプロパティを設定して、次を参照するようにする必要がありRectangle
ます。
Rectangle.prototype.constructor = Rectangle;
そのようにするのは、 と の関係が、仕様の §13.2 で示されRectangle.prototype
ているようにRectangle
見えるからです。基本的に、コンストラクター関数がある場合は、を参照する必要があります。クローン作成操作などでこれに依存することがあります (JavaScript 自体はそれに依存していません。たとえば、依存していません)。X
X.prototype.constructor
X
instanceof
したがって、ES5 を使用Object.create
してこれを行うことができます。しかし、今日でも、すべての JavaScript エンジンが をサポートしているわけではありませんObject.create
。代わりに、一時的なコンストラクター関数を作成し、それをプロパティとして借用Shape.prototype
させ、その一時的なコンストラクターを使用して as を使用する新しいオブジェクトを作成することにより、これを間接的に行うことができます。prototype
Rectangle.prototype
function Ctor() { }
Ctor.prototype = Shape.prototype; // Borrow the prototype
Rectangle.prototype = new Ctor(); // Create the new object
...また、constructor
プロパティを設定する必要があります。
Rectangle.prototype.constructor = Rectangle;
通常、毎回すべてを書き出すのではなく、次のようなヘルパーを使用します。
function derive(Parent, Child) {
function Ctor() { this.constructor = Child; }
Ctor.prototype = Parent.prototype;
Child.prototype = new Ctor();
return Child; // For chaining
}
次に、次のように使用します。
derive(Shape, Rectangle);
これらすべての最終結果は、インスタンスを初期化するためにShape
内から呼び出すだけです。Rectangle
create とは呼びませんRectangle.prototype
。
Lineage
JavaScript での継承の配管に興味がある場合は、上記を処理するスクリプトに興味があるかもしれません。私が「興味がある」と言うとき、必ずしもそれを使用することを意味するわけではありませんが (大歓迎ですが)、縮小されていないソースとこのページLineage
を見て、ヘルパーなしで同じことを行うことと比較すると、これがどのように行われるかがわかります。ものは動作します。