js継承の6つの方式を理解します.

18155 ワード

プロトタイプチェーン引継ぎ
プロトタイプチェーン継承はECMAScriptの主な継承方式です.その基本思想は原型を通じて複数の引用タイプの属性と方法を継承することである.プロトタイプチェーンとは何ですか各コンストラクタにはプロトタイプオブジェクトがあります.コンストラクタを呼び出して作成した例には、ポインターがあります.プロト.プロトタイプのオブジェクトを指すと、このプロトタイプは別のタイプの例かもしれないので、内部にももう一つのプロトタイプを指すポインタがあり、そのままプロトタイプのチェーンが形成されています.
  :
function SuperType() {
     
	this.property = true;
}
SuperType.prototype.getSuperValue = function() {
     
	return this.property;
};
function SubType() {
     
	this.subproperty = false;
}
//   SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function () {
      //                    ,       
	return this.subproperty; 
};
let instance = new SubType();
console.log(instance.getSuperValue()); // true
欠点1.親のインスタンスの属性が参照タイプである場合、実際には親クラスのインスタンス属性はサブクラスのプロトタイプ属性となり、サブクラスが作成したすべてのインスタンスはこれらの方法を共有し、例のこの属性を修正します.他のインスタンスの属性も修正されます.
コンストラクタ継承
プロトタイプが参照値を含む相続問題を解決するために、「構造関数の盗用」という技術が流行し始めました.「対象偽装」とか「古典継承」とも言われています.新しく作成したオブジェクトをコンテキスト実行関数としてcall()apply()の方法で使用できます.
function SuperType(name) {
     
  this.colors = ["red","blue","green"];
  this.name = name;
 }
function SubType(name) {
     
 //        ,  this         ,                           
  SuperType.call(this,name);
}
let instance1 = new SuperType('  ')
let instance2 = new SuperType('  ')
instance1.colors .push('yellow')
console.log(instance1) //{
     name:"  ",colors:["red","blue","green","yellow"]...}
console.log(instance2) //{
     name:"  ",colors:["red","blue","green"]...}

//                             (call  )
短所:1.構造関数でのみメソッド関数を呼び出すことができます.再利用できないのは、サブクラスがインスタンスを生成するたびに属性と方法を生成します.2.サブクラスは親タイプのプロトタイプにアクセスできません.
グループ引継ぎ
プロトタイプ鎖と構造関数を統合して,両者の利点を集中した.基本的な考え方はプロトタイプチェーンを使用してプロトタイプ上の属性と方法を継承し,構造関数によってインスタンス属性を継承することである.このように、方法をプロトタイプに定義して再使用を実現しても良いし、各インスタンスに独自の属性を持たせても良い.
function SuperType(name){
     
	this.name = name;
	this.colors = ["red","blue","green"];
}
SuperType.prototype.sayName = function() {
     
	console.log(this.name);
};
function SubType(name, age){
     
	//           
	SuperType.call(this, name);
	this.age = age;
}
//            
SubType.prototype = new SuperType();
SubType.prototype.sayAge = function() {
     
	console.log(this.age);
};
let instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
console.log(instance1.colors); //["red,blue,green,black"]
instance1.sayName(); // "Nicholas";
instance1.sayAge(); // 29
let instance2 = new SubType("Greg", 27);
console.log(instance2.colors); // ["red,blue,green"]
instance2.sayName(); // "Greg";
instance2.sayAge(); // 27

//            ,    ,   。                    
欠点は2回の父の構造関数を呼び出してメモリを消費します.
プロトタイプ継承
カスタムタイプでなくても、原型によってオブジェクト間の情報共有が可能です.
function  object(person) {
     
  function F() {
     }
  F.prototype = person
  return new F()
}

let person = {
     
  name:'  ',
  colors:['red','blue']
}

let person1 = object(person)
person1.colors.push('green')
let person2 = object(person)
person1.colors.push('yellow')
console.log(person) //['red','blue','green','yellow']
適用環境:オブジェクトがあります.それをもとに新しいオブジェクトを作成したいです.この対象をまずobjectに伝えてから、戻る対象を適切に修正する必要があります.Object.create()が最初のパラメータだけを伝えたとき、本質的には導入されたオブジェクトを浅い複製しました.欠点は新しいインスタンスの属性は全部後から追加されて、多重化できません.
寄生式引継ぎ
プロトタイプ継承と比較して近い継承方式は寄生型継承であり、寄生構造関数と工場モードのようなものである.継承を実現する関数を作成し、ある方法で対象を強化し、このオブジェクトに戻る.
function  object(person) {
     
  function F() {
     }
  F.prototype = person
  return new F()
}
function createAnother(original){
     
	let clone = object(original); //              
	clone.sayHi = function() {
      //            
	console.log("hi");
};
	return clone; //       
}
寄生式継承は,タイプや構造関数を気にせず,主要な対象に対しても同様である.短所:寄生式でオブジェクトに関数を追加すると関数の再利用が難しくなります.コンストラクターモードと似ています.
寄生式コンビネーション引継ぎ
最もよく使われている継承方式も最適であり、組み合わせ継承は2回の父親構造関数を呼び出し、効率的な問題があります.実は本質的にはサブプロトタイプは最終的には親類オブジェクトのすべての実例的な属性を含んでいます.サブ構造関数は実行時に自分のプロトタイプを書き換えるだけでいいです.基本的な考え方は、親の構造関数を呼び出してサブタイプのプロトタイプに値を付けるのではなく、親タイプのプロトタイプのコピーを取ることです.あくまで寄生式継承を使って親の原型を継承し、新たに返された対象をサブプロトタイプに与えます.
//    
function object(person) {
     
  function F(params) {
     }
  F.prototype = person
  return new F()
}
function inheritPrototype(SubType,SuperType) {
     
  let prototype = object(SuperType.prototype) //           

  //       constructor
  prototype.constructor = SubType

  //                 
  SubType.prototype = prototype
}

function SuperType(name) {
     
	this.name = name;
	this.colors = ["red","blue","green"];
}
SuperType.prototype.sayName = function() {
     
	console.log(this.name);
};
function SubType(name, age) {
     
	SuperType.call(this, name);
	this.age = age;
}

//  inheritPrototype         ,          
inheritPrototype(SubType, SuperType);

SubType.prototype.sayAge = function() {
     
	console.log(this.age);
};