まずは、JavaScript オブジェクトの継承とは何ですか? について詳しく調べてみましょう。
たとえば、「動物」オブジェクトのコンストラクターがあります。
function animal() { this.type = '动物'; }
「cat」オブジェクトのコンストラクターもあります。
function cat(name,color) { this.name = name; this.color = color; }
猫も動物であることはわかっています。この猫オブジェクトが動物オブジェクトの属性を継承したい場合、どうすればよいでしょうか?
コンストラクター バインディング
コンストラクター バインディングの使用は、call または apply を使用して親オブジェクトを自己オブジェクトにバインドするだけの最も簡単な方法です。
function cat(name,color) { animal.apply(this,arguments); this.name = name; this.color = color; } var cat1 = new cat("haha", 'red'); console.log(cat1.type); //动物
ただし、この方法は比較的まれです。
継承のコピー
親オブジェクトのプロパティとメソッドをすべて子オブジェクトにコピーすると、継承も実現できます。
function extend(Child, Parent) { var p = Parent.prototype; var c = Child.prototype; for (var i in p) { c[i] = p[i]; } c.uber = p; //桥梁作用 }
使用方法:
extend(cat, animal); var cat1 = new cat("haha","red"); alert(cat1.type); // 动物
プロトタイプ継承 (プロトタイプ)
上記の直接バインディングに比べて、プロトタイプの継承方法が一般的です。 プロトタイプについて、私なりに簡単にまとめてみました。
各関数には、オブジェクトへの参照であるプロトタイプ属性があります。new キーワードを使用して新しいインスタンスを作成すると、インスタンス オブジェクトはプロトタイプ オブジェクトからプロパティとメソッドを継承します。
言い換えると、「cat」コンストラクターのプロトタイプ属性が「animal」インスタンスを指している場合、「cat」オブジェクトのインスタンスが作成されると、「animal」オブジェクトのプロパティとメソッドが継承されます。
継承されたインスタンス
cat.prototype = new animal(); cat.prototype.constructor = cat; var cat1 = new cat("haha","red"); console.log(cat1.constructor == cat); //true console.log(cat1.type); // 动物
1. コードの最初の行では、cat 関数のプロトタイプ オブジェクトが、animal オブジェクト (animal の type 属性を含む) のインスタンスを指します。
2. コードの 2 行目は何を意味しますか?
1) まず、このコード行を追加しなかった場合は、
を実行します。 cat.prototype = 新しい動物();
console.log(cat.prototype.constructor == Animal); //true
言い換えれば、各プロトタイプ オブジェクトは実際に、そのコンストラクターを指すコンストラクター属性を持っています。
2)、以下のコードを見てみましょう
cat.prototype = new animal(); var cat1 = new cat("haha", 'red'); console.log(cat1.constructor == animal); //true
上記のことから、インスタンス cat1 のコンストラクターはanimalであることがわかり、明らかに間違っています。 。 。 cat1 は明らかに new cat() によって生成されているため、手動で修正する必要があります。 cat.prototype オブジェクトのコンストラクター値が cat に変更されます。
3) したがって、プロトタイプ オブジェクトを置き換える場合は、プロトタイプ オブジェクトのコンストラクター属性を手動で修正する必要があることに注意する必要があります。
o.prototype = {};
o.prototype.constructor = o;
プロトタイプを直接継承
animalオブジェクトでは、不変属性をanimal.prototypeに直接記述することができます。次に、cat.prototype がanimal.prototype を直接指すようにして、継承を実現します。
次に、動物オブジェクトを次のように書き換えてみましょう:
function animal() { } animal.prototype.type = '动物';
次に継承を実装します。
cat.prototype = animal.prototype; cat.prototype.constructor = cat; var cat1 = new cat("haha","red"); console.log(cat1.type); // 动物
前の方法と比較して、この方法はより効率的であり (動物のインスタンスは作成されません)、スペースを節約します。しかし、これは正しいことなのでしょうか?答えは不正解です。探し続けましょう。
cat.prototype = Animal.prototype;
このコード行では、cat.prototype と Animal.prototype が同じオブジェクトを指すようにするため、cat.prototype の特定の属性が変更されると、それがanimal.prototype に反映されますが、これは明らかに私たちが望んでいることではありません。
たとえば、次のように実行すると:
console.log(animal.prototype.constructor == Animal) //false
結果は false ですが、なぜですか? cat.prototype.constructor = cat; この行は、animal.prototype のコンストラクター属性も変更します。
空のオブジェクトを仲介者として使用する
var F = function(){}; F.prototype = animal.prototype; cat.prototype = new F(); cat.prototype.constructor = cat;
上記の 2 つの方法を組み合わせると、F は空のオブジェクトであるため、メモリをほとんど消費しません。この時点では、猫のプロトタイプ オブジェクトを変更しても、動物のプロトタイプ オブジェクトには影響しません。
console.log(animal.prototype.constructor == anime) // true
次に、上記のメソッドをカプセル化します。
function extend(Child, Parent) { var F = function(){}; F.prototype = Parent.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; Child.uber = Parent.prototype; }
使用する場合の方法は次のとおりです。
extend(cat,animal); var cat1 = new cat("haha","red"); console.log(cat1.type); // 动物
Child.uber = Parent.prototype; このコード行はブリッジとして機能し、子オブジェクトの uber 属性が親オブジェクトのプロトタイプ属性を直接ポイントできるようにします。これは、uber というチャネルを開くことと同じです。自己オブジェクト。これにより、子オブジェクトのインスタンスが親オブジェクトのすべてのプロパティとメソッドを使用できるようになります。
上記は JavaScript オブジェクトの継承についての私の理解です。お読みいただきありがとうございます。