一般的に言えば、オブジェクトのすべてのインスタンスに対してまったく同じ値に初期化されることを意図したtotalやのようなプロパティは、コンストラクタではなく で定義する必要があります。distancesubSectionprototype
オブジェクトprototypeは基本的に、そのオブジェクトのすべてのインスタンスが基づいている「テンプレート」です。すべてのインスタンスには、 で定義された各プロパティとメソッドがありprototypeます。
したがって、3 つの「クラス」 (JavaScript には、Java のような古典的な継承言語で定義されているクラスはありませんが、これらの言語に慣れている人にとっては用語を使用する方が簡単な場合があります) は、次のように宣言する必要があります。
function subSection(pattern) {
this.pattern = pattern;
}
function enhancer(pattern) {
this.pattern = pattern;
}
function silencer(pattern) {
this.pattern = pattern;
}
コンストラクタの外に出て、プロトタイプに移動totalします。distancesubSectionsubSection
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のインスタンスはコンストラクターを誤って参照します。enhancersilencerconstructorenhancersilencersubSection
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;
}
EmployeePerson同じコンストラクター引数のセットを共有していなくても、から継承できる必要があります。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、コンストラクターは引数を期待しないため、各インスタンスのクリーンなプロトタイプになります。
これは必須ではありませんが、プロトタイプの継承をセットアップするためのよりクリーンな方法です。未定義のプロパティでプロトタイプを乱雑にする理由はあまりありません。