Javascriptがオブジェクト指向を取り巻くように頭を曲げようとしていますが、他の多くの場合と同様に、constructor
プロパティに関する混乱に直面しています。特に、constructor
プロパティの重要性は、効果を持たせることができないようです。例えば。:
function Foo(age) {
this.age = age;
}
function Bar() {
Foo.call(this, 42);
this.name = "baz";
}
Bar.prototype = Object.create(Foo.prototype);
var b = new Bar;
alert(b.constructor); // "Foo". That's OK because we inherit `Foo`'s prototype.
alert(b.name); // "baz". Shows that Bar() was called as constructor.
alert(b.age); // "42", inherited from `Foo`.
上記の例では、オブジェクトb
には(Bar
)と呼ばれる適切なコンストラクターがあり、Foo
からageプロパティを継承しています。なぜ多くの人々がこれを必要なステップとして提案するのですか:
Bar.prototype.constructor = Bar;
明らかに、正しいBar
コンストラクターwasはb
を構築するときに呼び出されるので、このプロトタイププロパティにはどのような影響がありますか?コンストラクタープロパティを「正しく」設定することで実際にどのような違いが生じるか知りたいのですが、オブジェクトが作成された後に実際に呼び出されるコンストラクターに影響を与えることがわかりません。
constructor
プロパティは、内部的には実際的な違いはまったくありません。コードで明示的に使用している場合にのみ使用できます。たとえば、オブジェクトを作成した実際のコンストラクター関数への参照を各オブジェクトに必要とする場合があります。その場合は、例のように、コンストラクタ関数のconstructor
プロパティにオブジェクトを割り当てることにより、継承をセットアップするときに、prototype
プロパティを明示的に設定する必要があります。
ステップ1は、constructor
とprototype
が何であるかを理解することです。難しいことではありませんが、古典的な意味での「継承」を手放さなければなりません。
コンストラクター
constructor
プロパティしないは、プログラムで特定の効果を引き起こしますが、どの関数がnew
演算子と組み合わせて使用されたかを確認することができます。オブジェクトを作成します。 new Bar()
と入力するとBar
になり、_new Foo
_ itと入力するとFoo
になります。
プロトタイプ
prototype
プロパティは、問題のオブジェクトに要求されたプロパティがない場合のルックアップに使用されます。 _x.attr
_と書くと、JavaScriptはattr
の属性の中からx
を見つけようとします。見つからない場合は、_x.__proto__
_を検索します。存在しない場合は、_x.__proto__.__proto__
_が定義されている限り、___proto__
_などを検索します。
それでは、___proto__
_とは何ですか?また、prototype
とは何の関係がありますか?端的に言えば、prototype
は「タイプ」用で、___proto__
_は「インスタンス」用です。 (型とインスタンスの間に実際には違いがないため、引用符で言います)。 x = new MyType()
を記述すると、(とりわけ)起こることは_x.__proto___
_が_MyType.prototype
_に設定されることです。
質問
さて、あなた自身の例が何を意味するのかを導き出すために必要なのは上記だけですが、実際の質問に答えてみてください。 「なぜ次のように書く」:
_Bar.prototype.constructor = Bar;
_
私は個人的にそれを見たことがなく、少し馬鹿げていると思いますが、あなたがそれを与えた文脈では、_Bar.prototype
_-オブジェクト(new Foo(42)
を使用して作成された)が持っているようになりますBar
ではなくFoo
によって作成されます。タイプルックアップ(constructor
プロパティ)が、より一般的なオブジェクトのタイプではなく、常に最も具体的なタイプを常に生成するC++/Java/C#のような言語に似たものを作成するものであると思いますプロトタイプチェーンに追加します。
私のアドバイス:JavaScriptの「継承」についてはあまり考えないでください。インターフェースとミックスインの概念はより理にかなっています。また、オブジェクトのタイプをチェックしないでください。代わりに、必要なプロパティを確認してください(「アヒルのように歩き、アヒルのように鳴くなら、それはアヒルです」)。
混乱を引き起こすのは、JavaScriptが上記のプロトタイプ機構だけである場合にJavaScriptを古典的な継承モデルに強制しようとすることです。 constructor
- propertyを手動で設定することを提案した多くの人々は、おそらくそれをやろうとしました。抽象化は問題ありませんが、このコンストラクタープロパティの手動割り当ては、JavaScriptのあまり一般的な使用法ではありません。
コンストラクターを使用する1つのケース:
これは、継承の一般的な実現方法の1つです。
_Function.prototype.extend = function(superClass,override) {
var f = new Function();
f.prototype = superClass.prototype;
var p = this.prototype = new f();
p.constructor = this;
this.superclass = superClass.prototype;
...
};
_
このnew f()
はsuperClassのコンストラクターを呼び出さないため、subClassを作成するときに、次のように最初にsuperClassを呼び出す必要があります。
_SubClass = function() {
SubClass.superClass.constructor.call(this);
};
_
そのため、コンストラクタープロパティはここで意味があります。
prototype.constructor
プロパティがprototype
プロパティの再割り当てに耐えるようにするユースケースの1つは、prototype
で同じタイプの新しいインスタンスを生成するメソッドを定義する場合です。指定されたインスタンス。例:
function Car() { }
Car.prototype.orderOneLikeThis = function() { // Clone producing function
return new this.constructor();
}
Car.prototype.advertise = function () {
console.log("I am a generic car.");
}
function BMW() { }
BMW.prototype = Object.create(Car.prototype);
BMW.prototype.constructor = BMW; // Resetting the constructor property
BMW.prototype.advertise = function () {
console.log("I am BMW with lots of uber features.");
}
var x5 = new BMW();
var myNewToy = x5.orderOneLikeThis();
myNewToy.advertise(); // => "I am BMW ..." if `BMW.prototype.constructor = BMW;` is not
// commented; "I am a generic car." otherwise.
コンストラクタープロパティは、オブジェクトインスタンスの作成に使用されたコンストラクターを指します。 「new Bar()」と入力すると「Bar」になり、「new Foo()」と入力すると「Foo」になります。
ただし、コンストラクタを設定せずにプロトタイプを設定すると、次のような結果が得られます。
function Foo(age) {
this.age = age;
}
function Bar() {
this.name = "baz";
}
Bar.prototype = new Foo(42);
var one = new Bar();
console.log(one.constructor); // 'Foo'
var two = new Foo();
console.log(two.constructor); // 'Foo'
コンストラクターを実際にオブジェクトの作成に使用されたコンストラクターに設定するには、次のようにプロトタイプを設定する際にコンストラクターも設定する必要があります。
function Foo(age) {
this.age = age;
}
function Bar() {
this.name = "baz";
}
Bar.prototype = new Foo(42);
Bar.prototype.constructor = Bar;
var one = new Bar();
console.log(one.constructor); // 'Bar'
var two = new Foo();
console.log(two.constructor); // 'Foo'