関数のプロパティconstructor
のprototype
プロパティは、関数を指すように意図されているため、オブジェクトにそれを構築したものを尋ねることができます。これは、関数オブジェクトの作成の一部として自動的に設定されます (仕様のセクション 13.2 を参照してください[または、より最新のバージョンについてはこちら])。それを変更しますが、デフォルトではそれが目的です。何年もの間、JavaScript 仕様は、プロパティがそこにあり、既定値が指定されていることだけを述べていました (つまり、既定値は.)。しかし、ES2015 以降ではそれが変更され、仕様のさまざまな操作で実際に次のようなプロパティが使用されるようになりました。constructor
Foo.prototype
constructor
function Foo() { }
Foo.prototype.constructor
Foo
constructor
ここ、ここ、ここ、そしてここ。
(以下は ES2015 のclass
機能が追加される前に書かれたものであることに注意してください。以下は、ES5 以前でこれを行う方法です。ES2015+ では、コンストラクター関数と継承階層を行っている場合、以下を行う正当な理由はありません。class
[コンストラクター関数を使用して継承階層を構築しない場合 (その必要がない場合、JavaScript でそれらを行う方法は他にもあります — 以下のことを実行したり、 を使用したりclass
することはありません。])
継承に関連して、オーバーライドできるのには十分な理由があります。Base
基本オブジェクトを作成するコンストラクターと、 の機能に加えて の追加/変更を加えたDerived
派生オブジェクトを作成するコンストラクターが必要であるとします。通常の(私の考えでは理想的ではありませんが)完了したことを確認する方法(ヘルパースクリプトがない場合)は次のとおりです。Base
Derived
function Base() {
}
Base.prototype.foo = function() {
console.log("I'm Base#foo");
};
function Derived() {
}
Derived.prototype = new Base(); // So we get all the `Base` stuff
Derived.prototype.bar = function() {
console.log("I'm Derived#bar");
};
var d = new Derived();
d.foo(); // "I'm Base#foo"
d.bar(); // "I'm Derived#bar"
問題はd.constructor === Base
、Derived
. したがって、それを修正できることが重要です。
...
Derived.prototype = new Base(); // So we get all the `Base` stuff
Object.defineProperty(Derived.prototype, "constructor", { // Fix up
value: Derived,
writable: true,
configurable: true
});
...
(補足: このすべての配管 (およびスーパーコールに関する複雑さ) が、ES2015+ にclass
構文がある理由です。)
上記は、継承階層を設定するための理想的な方法ではないことに注意してください。これは通常目にするものですが、上で述べたように、理想的ではありません。完全を期すために、ES5 構文に制限された環境では、これが優れています。
function Base() {
}
Base.prototype.foo = function() {
console.log("I'm Base#foo");
};
function Derived() {
Base.call(this); // So Base sets up its stuff
}
Derived.prototype = Object.create(Base.prototype); // So we get all the `Base` stuff
Object.defineProperty(Derived.prototype, "constructor", {
value: Derived,
writable: true,
configurable: true
});
Derived.prototype.bar = function() {
console.log("I'm Derived#bar");
};
var d = new Derived();
d.foo(); // "I'm Base#foo"
d.bar(); // "I'm Derived#bar"
...ES5 以前の環境では、シム/ポリフィルを使用しますObject.create
。しかし、繰り返しになりますが、これを直接行うことはありません (また、お勧めしません)。ヘルパー スクリプトを使用するので、宣言型で反復可能です。