全面分析JavaScript継承


ES 6の前に、JavaScriptはこの既存のメカニズムを引き継いでいませんでした。
ES 5の継承方式
クラス継承

//    
function Father(){
this.fatherVal = 'father';
}
//         
Father.prototype.getFatherValue = function(){
return this.fatherVal;
}
//     
function Child(){
this.childVal = 'child';
}
//    
Child.prototype = new Father();
//         
Child.prototype.getChildValue = function(){
return this.childVal;
}


サブタイプのプロトタイプは親タイプの例を与えられ、新しく作成されたオブジェクトは親タイプのコンストラクター内の属性と方法をコピーし、プロトタイプを変更します。プロト父類のプロトタイプのオブジェクトを指します。このようにして、父類のプロトタイプのオブジェクト上の属性と方法と父類のコンストラクタにコピーされた属性と方法があります。

var instance = new Child();
console.log(instance.getFatherValue()); //father
console.log(instance.getChildValue()); //child
console.log(instance instanceof Child); //true
console.log(instance instanceof Father); //true
console.log(instance instanceof Object); //true
console.log(Child instanceof Father); //false
console.log(Child.prototype instanceof Father); //true


短所:
1.サブクラスのインスタンスは、親タイプの共有参照属性を共有する。
2.親の構造関数内の属性を参照初期化できませんでした。

function Father(){
this.companies =['bigo','yy','uc']
}
funtion Child(){}
Child.prototype = new Father();
var instanceA = new Child();
var instanceB = new Child();
console.log(instanceB.companies); //['bigo','yy','uc']
instanceA.companies.push('nemo');
console.log(instanceB.companies); //['bigo','yy','uc','nemo']
コンストラクタ継承

//    
function Father(val){
this.companies =['bigo','yy','uc']
this.val = val;
}
//        
Father.prototype.getCom = function(){
console.log(this.companies);
}
//    
function Child(val){
//  
Father.call(this,val);
}
var instanceA = new Child('childA');
var instanceB = new Child('childB');
instanceA.companies.push('nemo');
console.log(instanceA.companies); //['bigo','yy','uc','nemo']
console.log(instanceA.val); //childA
console.log(instanceB.companies); //['bigo','yy','uc']
console.log(instanceB.val); //childB
Childに対してコールを呼び出し、サブクラスの変数を親クラスで一回実行し、父類をthisにバインディングするので、サブクラスは親クラスの共有属性を継承します。
短所:
このタイプの継承はプロトタイプタイプがないので、父タイプのプロトタイプは布団類では継承されません。掛け布団類の継承はコンストラクションに置かなければなりません。このように作成された各インスタンスはそれぞれ一つの部分を持っています。共有できません。
グループ引継ぎ

//    
function Father(val){
this.companies =['bigo','yy','uc']
this.val = val;
}
//        
Father.prototype.getValue = function(){
console.log(this.val);
}
//    
function Child(val,newVal){
//       
Father.call(this,val);
this.newVal = newVal;
}
//    
Child.prototype = new Father();
//        
Child.prototype.getNewValue = function(){
console.log(this.newVal);
}
var instanceA = new Child("fatherA","childA");
instanceA.companies.push('nemo');
console.log(instanceA.companies); //['bigo','yy','uc','nemo']
instanceA.getValue(); //fatherA
instanceA.getNewValue(); //childA
var instanceB = new Child("fatherB","childB");
console.log(instanceA.companies); //['bigo','yy','uc']
instanceB.getValue(); //fatherB
instanceB.getNewValue(); //childB


短所:
構造関数の継承を使用して、父親のクラスの構造関数を実行し、サブクラスのプロトタイプのクラス継承を実現するために、父親のクラスの構造関数を再起動しました。父の構造関数は2回呼び出されました。
プロトタイプ継承

function inheritObject(obj){
function F(){};
F.prototype = obj;
return new F();
}
var situation = {
companies:['bigo','yy','uc'];
area:'guangzhou';
}
var situationA = inheritObject(situation);
situationA.area = 'shenzhen';
situationA.companies.push('tencent');
var situationB = inheritObject(situation);
situationB.area = 'beijing';
situationB.companies.push('baidu');
console.log(situationA.area); //shenzhen
console.log(situationA.companies); //['bigo','yy','uc','tencent','baidu']
console.log(situationB.area); //beijing
console.log(situationB.companies); //['bigo','yy','uc','tencent','baidu']
console.log(situation.area); //guangzhou
console.log(situation.companies); //['bigo','yy','uc','tencent','baidu']


クラス継承の一つのパッケージであり、その中の移行対象はクラス継承のサブクラスに相当し、新しい実用化対象に戻る。
短所:
類式継承と同様に、親類の共有引用属性が共有されています。
寄生式引継ぎ

function inheritObject(obj){
function F(){};
F.prototype = obj;
return new F();
}
var situation = {
companies:['bigo','yy','uc'];
area:'guangzhou';
}
function createSituation(obj){
//           
var newObj = new inheritObject(obj);
//       
newObj.getArea = function(){
console.log(newObj.area)
}
//    
return obj;
}


プロトタイプ継承のもとに新しい属性と方法を追加しただけですか?それともプロトタイプ継承と同じ欠点ですか?
寄生式コンビネーション引継ぎ

function inheritObject(obj){
function F(){};
F.prototype = obj;
return new F();
}
//     child,parent     
function inheritPrototype(child,parent){
//                 ;
var fatherProto = inheritObject(father.prototype);
//               constructor     ;
fatherProto.constructor = child;
//       
child.prototype = fatherProto;
}
//    
function Father(val){
this.companies =['bigo','yy','uc']
this.val = val;
}
//        
Father.prototype.getValue = function(){
console.log(this.val);
}
//    
function Child(val,newVal){
//       
Father.call(this,val);
this.newVal = newVal;
}
//    
Child.prototype = new Father();
inheritPrototype(Child,Father);
//        
Child.prototype.getNewValue = function(){
console.log(this.newVal);
}


1.構造関数の継承において、私たちはすでに父の構造関数を呼び出しました。もう一つの原型のコピーが足りません。
2.原型継承によって副本が得られますが、この時にはfatherProtoのconstructorがサブクラスを指す必要があります。
3.最後に副本fatherProtoをサブタイプのプロトタイプに割り当てます。
全体としては、構造関数だけでなく、プロトタイプの継承が必要ですが、父の構造関数の呼び出しの2回の組み合わせを避けるために、最大の変更は、サブタイプのプロトタイプに与えられた式父のプロトタイプの1つの参照です。

var instanceA = new Child("fatherA","childA");
instanceA.companies.push('nemo');
console.log(instanceA.companies); //['bigo','yy','uc','nemo']
instanceA.getValue(); //fatherA
instanceA.getNewValue(); //childA
var instanceB = new Child("fatherB","childB");
console.log(instanceA.companies); //['bigo','yy','uc']
instanceB.getValue(); //fatherB
instanceB.getNewValue(); //childB

注意点:
この場合、サブクラスにプロトタイプを追加する必要がある場合は、プロトタイプの文法で一つずつ追加しなければなりません。そうでないと、親タイプを継承するプロトタイプのオブジェクトが上書きされます。
ES 6にClass文法が追加されました。Classはextendsのキーワードによって継承されます。ES 5の修正により、原型チェーンの継承が実現されます。
クラス引継ぎ

class Parent {
constructor(value) {
this.val = value
}
getValue() {
console.log(this.val)
}
}
class Child extends Parent {
constructor(value) {
super(value)
}
}
let child = new Child(1)
child.getValue() // 1
child instanceof Parent // true

classの継承を実現する核心は、extensを使用してどの親類から継承されるかを示し、またサブ構造関数でsuperを呼び出す必要があります。このコードはPartent.call(this,value)と見なされます。
サブクラスにconstructorの定義がない場合、この方法はデフォルトで追加されます。
以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。