受け入れられた答えは間違いなくうまくいくでしょう。そして、この「短い」説明はとりとめのないものになりましたが、役に立てば幸いです.
受け入れられた答えで注意しなければならないことが1つあります。基本的に「継承」するときBar.prototype = new Foo()
は、コンストラクターを呼び出しています。したがって、別の「クラス」の起動パッドとして使用されることを想定していないコードがコンストラクターにある場合、奇妙な結果が発生します。たとえば、次のようにします。
var Person = function (firstName, lastName) {
....
};
var Student = function (firstName, lastName, grade) {
....
};
Student
の拡張だとしましょうPerson
。でプロトタイプをどのように構築しStudent
ますか? たぶん好きじゃないStudent.prototype = new Person("John", "Doe");
もう少し複雑ですが、別の関数内にラップできる別の処理方法は次のとおりです。
var extend = function (child, parent) {
var f = function () {};
f.prototype = parent.prototype;
child.prototype = new f();
child.prototype.constructor = parent;
}
var Person = function (firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
Person.prototype.getName = function () {
return this.firstName + " " + this.lastName;
}
Person.prototype.setAge = function (age) {
this.age = age;
}
var Student = function (firstName, lastName, grade) {
Person.call(this, firstName, lastName);
this.grade = grade;
};
extend(Student, Person); //<< do this before adding stuff to the prototype
Student.prototype.getName = function () {
var name = Person.prototype.getName.apply(this);
return name + ", Grade " + this.grade;
}
Student.prototype.tooOldToBeAStudent = function () {
if(this.age > 18) { return true; }
}
var p = new Person("Joe", "DiMaggio");
var s = new Student("Jack", "Sparrow", 12);
console.log(p.getName(), s.getName());
//consoles "Joe DiMaggio" "Jack Sparrow, Grade 12"
console.log(s instanceof Person);
//true - even with the weird looking inheritance, Student is still an instance of Person.
s.setAge(30);
console.log(s.age);
//30, just like what you'd expect with a Person object.
console.log(s.tooOldToBeAStudent);
//true - as mentioned previously, 'age' is set via its inherited method.
これにより、Person 機能だけでなく、その上に構築することができます。継承で実際に行うことのようなものです。
それはどのように機能しますか?素晴らしい質問です。まず、オブジェクトは[基本的に]参照によって割り当てられます。プロトタイプはオブジェクトです。そのため、extend
関数では、 のサロゲートとして機能する空の関数を作成しますchild
。これにより、 のプロトタイプがそれ自体にコピーparent
され、それ自体の新しいインスタンスが のプロトタイプになりchild
ます。このようにparent
のコンストラクターは呼び出されませんが、親のプロトタイプは引き続き使用されます。instanceof
それでも機能することを確認するために、 は -child.prototype.constructor
に設定されparent
、子がサロゲートからではなく親から来たことを効果的に通知する JavaScript に設定されます。
また、メソッドをオーバーライドするときは、継承元の「クラス」のプロトタイプ メソッドを使用できます。apply
これcall
によりthis
、現在のオブジェクトのスコープでメソッドを実行し、好きなように感じる任意の引数を渡すことができますが、それらは受け入れられます。あなたが選ぶ機能。たとえば、生徒の現在のインスタンスのコンテキストでPerson.prototype.getName.apply(this);
Person を実行します。getName
setAge をオーバーライドして、年齢を単純に console.logout したいとしましょう。
Student.prototype.setAge = function () {
Person.prototype.setAge.apply(this, arguments);
console.log(this.age);
}
ここで起こっているPerson
のは、setAge
に渡された引数を使用して が呼び出されていることStudent
ですsetAge
。したがって、基本的には、元のメソッドの引数の詳細を知らなくても、ものを通過させることができます。