一般的に言えば、オブジェクトのすべてのインスタンスに対してまったく同じ値に初期化されることを意図したtotal
やのようなプロパティは、コンストラクタではなく で定義する必要があります。distance
subSection
prototype
オブジェクトprototype
は基本的に、そのオブジェクトのすべてのインスタンスが基づいている「テンプレート」です。すべてのインスタンスには、 で定義された各プロパティとメソッドがありprototype
ます。
したがって、3 つの「クラス」 (JavaScript には、Java のような古典的な継承言語で定義されているクラスはありませんが、これらの言語に慣れている人にとっては用語を使用する方が簡単な場合があります) は、次のように宣言する必要があります。
function subSection(pattern) {
this.pattern = pattern;
}
function enhancer(pattern) {
this.pattern = pattern;
}
function silencer(pattern) {
this.pattern = pattern;
}
コンストラクタの外に出て、プロトタイプに移動total
します。distance
subSection
subSection
subSection.prototype.total = 0;
subSection.prototype.distance = 0;
subSection
次のステップは、間のプロトタイプの継承を設定し、それらの間の一種のプロキシとして no-op 関数を使用することですenhancer
:silencer
function fn() {}
fn.prototype = subSection.prototype;
enhancer.prototype = new fn();
silencer.prototype = new fn();
最後に、とプロトタイプのconstructor
プロパティを正しいオブジェクトに設定して、インスタンスのプロパティが適切なコンストラクタ関数を参照するようにします。この手順を実行しない場合、orのインスタンスはコンストラクターを誤って参照します。enhancer
silencer
constructor
enhancer
silencer
subSection
enhancer.prototype.constructor = enhancer;
silencer.prototype.constructor = silencer;
enhancer
これでandオブジェクトをインスタンス化できます。silencer
結果のインスタンスにはtotal
、anddistance
プロパティとconstructor
、それぞれのオブジェクトを参照するプロパティがあります。
var a, b;
a = new enhancer('aaaa');
b = new silencer('bbbb');
console.log(a.total + ', ' + a.distance); // 0, 0
console.log(b.total + ', ' + b.distance); // 0, 0
console.log(a.constructor); // (string representation of enhancer constructor)
継承プロセス中に関数をプロキシとして使用する理由はfn
、オブジェクトが、必ずしも同じコンストラクター引数のセットを持たない別のオブジェクトから継承できる必要があるためです。
次の 2 つのコンストラクタがあるとします。
function Person(name, age, hometown) {
this.name = name;
this.age = age;
this.hometown = hometown;
}
function Employee(name, company, title) {
this.name = name;
this.company = company;
this.title = title;
}
Employee
Person
同じコンストラクター引数のセットを共有していなくても、から継承できる必要があります。Employee.prototype
の新しいインスタンスと等しくなるように単純に設定した場合Person
、Employee
プロトタイプには と の 3 つの未定義のプロパティname
が含まage
れhometown
ます。
Employee.prototype = new Person; // name, age and hometown are undefined
var e = new Employee('John Smith', 'New York Times', 'editor'); // e's prototype has undefined properties name, age and hometown
no-op 関数fn
(事実上好きな名前を付けることができます) を使用するとfn
、コンストラクターは引数を期待しないため、各インスタンスのクリーンなプロトタイプになります。
これは必須ではありませんが、プロトタイプの継承をセットアップするためのよりクリーンな方法です。未定義のプロパティでプロトタイプを乱雑にする理由はあまりありません。