js における継承は、オブジェクトの偽装とプロトタイプ チェーンの 2 つのタイプに分類できます。
1. オブジェクトの偽装には、一時属性メソッド、call()、apply() メソッドの 3 種類があります。
1. 一時属性メソッド
次のようにコードをコピーします。
関数 人(名前){
this.name = 名前;
this.say = function(){
alert('私の名前は '+this.name);
}
}
関数 F2E(名前, ID){
this.temp = 人;
this.temp(名前);
this.temp を削除します。
this.id = ID;
this.showId = function(){
alert('おはようございます、先生、私の仕事番号は '+this.id);
}
}
var simon = 新しい F2E('Simon',9527);
サイモン.say();
simon.showId();
2.call()/apply()メソッド
基本的に、このポインタのポインタを変更します。
次のようにコードをコピーします。
関数 人(名前){
this.name = 名前;
this.say = function(){
alert('私の名前は '+this.name);
}
}
関数 F2E(名前, ID){
Person.call(this,name); //apply() メソッドが Person.apply(this,new Array(name)) に変更されました。
this.id = ID;
this.showId = function(){
alert('おはようございます、先生、私の仕事番号は '+this.id);
}
}
var simon = 新しい F2E('Simon',9527);
サイモン.say();
simon.showId();
欠点: まず、このメモリ割り当て図を見てみましょう。
OO の概念では、new がインスタンス化された後、オブジェクトはヒープ メモリ内に独自のスペースを形成します。このコード セグメントは注目に値します。メンバー メソッドはこのコード セグメント内に存在し、メソッドは共有されます。問題は、オブジェクトの偽装を通じて継承する場合、すべてのメンバー メソッドがこれを指すことになります。つまり、新規作成後、各インスタンスがこのメンバー メソッドを持つことになり、大量のメモリが浪費されます。また、オブジェクトの偽装では、プロトタイプで定義された変数やメソッドを継承することはできません。たとえば、次のコードではエラーが発生します。
次のようにコードをコピーします。
関数 人(名前){
this.name = 名前;
this.say = function(){
alert('私の名前は '+this.name);
}
}
人物.プロトタイプ.年齢 = 20;
person.prototype.sayAge = function(){alert('私の年齢は '+this.age)};
関数 F2E(名前, ID){
Person.apply(this,新しい配列(名前));
this.id = ID;
this.showId = function(){
alert('おはようございます、先生、私の仕事番号は '+this.id);
}
}
var simon = 新しい F2E('Simon',9527);
simon.sayAge(); //プロンプト TypeError: simon.sayAge は関数ではありません
2. プロトタイプチェーン方式
次のようにコードをコピーします。
関数 人(){
this.name = 'サイモン';
}
person.prototype.say = function(){
alert('私の名前は '+this.name);
}
関数 F2E(id){
this.id = ID;
this.showId = function(){
alert('おはようございます、先生、私の仕事番号は '+this.id);
}
}
F2E.prototype = 新しい人();
var simon = 新しい F2E(9527);
サイモン.say();
simon.showId();
alert(simon.hasOwnProperty('id')) //それが独自のプロパティであるかどうかを確認します
次に、上記の例に従って、次の JS プロトタイプ チェーンの概念を理解します。
プロトタイプ チェーンは、次のように理解できます。js 内の各オブジェクトには、隠された __proto__ 属性があり、インスタンス化されたオブジェクトの __proto__ 属性は、そのクラスのプロトタイプ メソッドを指し、このプロトタイプ メソッドは、別のインスタンス化されたオブジェクトである __proto__ に割り当てることができます。このオブジェクトはそのクラスを指す必要があるため、チェーンが形成されます。
次のようにコードをコピーします。
F2E.prototype = 新しい人()
この一文が鍵です。 js オブジェクトが特定の属性を読み取るとき、まず独自の属性を検索します。属性がない場合は、プロトタイプ チェーン上のオブジェクトの属性を検索します。つまり、プロトタイプチェーンのメソッドを共有できるため、オブジェクトの偽装やメモリの浪費の問題が解決されます。
次に、デメリットについて説明します。
欠点は明らかです。プロトタイプ チェーンの継承では、サブクラスをインスタンス化するときにパラメーターを親クラスに渡すことができないため、この例の関数 Person() にはパラメーターがなく、this.name="Simon" として直接記述されます。次のコードでは、望ましい効果は得られません。
次のようにコードをコピーします。
関数 人(名前){
this.name = 名前;
}
person.prototype.say = function(){
alert('私の名前は '+this.name);
}
関数 F2E(名前, ID){
this.id = ID;
this.showId = function(){
alert('おはようございます、先生、私の仕事番号は '+this.id);
}
}
F2E.prototype = 新しい人();
var simon = 新しい F2E("Simon",9527);
サイモン.say();
simon.showId();
関数 人(名前){
this.name = 名前;
}
person.prototype.say = function(){
alert('私の名前は '+this.name);
}
関数 F2E(名前, ID){
this.id = ID;
this.showId = function(){
alert('おはようございます、先生、私の仕事番号は '+this.id);
}
}
F2E.prototype = new Person(); //値をここに渡すことはできません。this.name も name も機能しません。F2E.prototype = new Person('wood') と書くこともできますが、この場合は simon です。 Say() は私の名前はウッドになります
var simon = 新しい F2E("Simon",9527);
simon.say(); //ポップアップ 私の名前は未定義です
simon.showId();
最後に、継承を実装するためのより良い方法だと思うことをまとめておきます。メンバー変数はオブジェクト偽装を使用し、メンバー メソッドはプロトタイプ チェーンを使用します。コードは次のとおりです。
次のようにコードをコピーします。
関数 人(名前){
this.name = 名前;
}
person.prototype.say = function(){
alert('私の名前は '+this.name);
}
関数 F2E(名前, ID){
パーソン.call(この,名前);
this.id = ID;
}
F2E.prototype = 新しい人();
//ここで 1 つの詳細に注意してください。showId は F2E.prototype = new Person(); の前に書くことはできません。
F2E.prototype.showId = function(){
alert('おはようございます、先生、私の仕事番号は '+this.id);
}
var simon = 新しい F2E("Simon",9527);
サイモン.say();
simon.showId();