JS中的多種繼承方式(第12天)

qq_32021429發表於2020-10-24

JS中的多種繼承方式(第12天)

//----------------JS中的多種繼承方式------------------
/* 
 * JS本身是基於物件導向開發的程式語言
    => 類:封裝、繼承、多型

    封裝:類也是一個函式,把實現一個功能的程式碼進行封裝,以此實現“低耦合,高內聚”
    多型:過載、重寫
      =>過載:相同的方法名,由於引數型別/個數或者方法返回的值不同,具備了不同的功能(JS不具備嚴格意義上的過載,JS中的過載:同一個方法內,根據傳參的不同實現不同的功能)
      =>重寫:子類重寫父類上的方法(伴隨著繼承執行的)
    繼承:子類繼承父類中的方法

  繼承的目的:讓子類的例項同時也具備父類中的私有屬性和公共的方法
*/


function Father() {
  this.father_name = 'father';
  this.sum = function(){
    console.log(11);
  }
}
Father.prototype.getName = function(){
  console.log(this.name);
}

function Son(){
  this.name = 'son';
}

/* 
// 原型鏈繼承:讓子類的原型指向父類的例項
Son.prototype = new Father; 
// 重定向原型之後記得手動補上 constructor
Son.prototype.constructor = Son;

// 原型鏈繼特點:
//  1、父類中私有的屬性和方法最後都變成了子類例項共有的
//  2、原型繼承並不是把父類的屬性和方法“拷貝”給子類,而是讓子類例項基於__proto__原型鏈查詢到父類和子類定義的屬性和方法
//  3、子類例項基於__proto__修改子類原型上的內容,只會對子類的其他例項造成影響,並不會影響父類的例項,但是如果是修改子類原型的原型鏈中的內容(即 子類例項.__proto__.__proto__),這樣修改的是父類的原型,那受影響的不僅是父類的例項,子類的其他例項也會受影響
 
 */


/* 
 // call繼承(也叫借用建構函式繼承):在子類中將父類作為普通函式執行,同時將父類中的this改為子類的例項
function Son(){
  // 在子類的建構函式中把父類當做普通函式執行,將函式中的this改為子類的例項
  Father.call(this);// 改變Father中的this指向
  this.name = 'son';
}
// call繼承的特點:
//  1、子類只能繼承父類中私有的屬性和方法,不能繼承父類原型上的屬性和方法
//  2、子類繼承過來的屬性也變成了子類私有的
 */


 // 組合繼承:原型繼承 + call繼承
/*  function Son(){
   Father.call(this);
   this.sonName = 'son';
 }
 Son.prototype = new Father;
 Son.prototype.constructor = Son;

 // 組合繼承的特點:
 //  1、子類繼承父類的私有屬性變成自己的私有屬性,繼承公有屬性和方法變成子類公有的
 //  2、父類私有的屬性和方法也會繼承(拷貝)在子類的公有屬性和方法中
 // console.log(f.sum === f.__proto__.sum); // false
 // !注意:這種方式會把父類的私有屬性和方法同時拷貝給子類的私有和公有,且子類繼承過來的私有和公用方法不是同一個(堆地址不同) 
 //  => 子類例項.私有方法(從父類繼承過來的) !== 子類例項.__proto__.方法(從父類繼承過來的)
 */


/*  // 寄生組合繼承:在組合繼承的方法上進行改進
 function Son(){
   Father.call(this);
   this.sonName = 'son';
 }

 // Object.create(protoObj):建立一個空的物件,讓這個空物件的__proto__指向 protoObj
 Son.prototype = Object.create(Father.prototype);
 Son.prototype.constructor = Son; */

  /* // Object.create 的實現
Object.create = function(proto){
  function anmouse(){}
  anmouse.prototype = proto
  return new anmouse;
}
console.log(Object.create(Son)) */

Son.prototype.getSonName = function(){
  console.log(this.name)
}

let f = new Son;
let p = new Son;



// ---------- ES6中的類的繼承-------------
class Person{
  constructor(name) {
    this.person = name;
  }
  // 用等號的是設定私有的方法
  sum = function(){
    console.log(222)
  }
  // 直接寫的是設定公有的方法
  getPerson(){
    console.log(111)
  }
}
// 繼承:子類 extends 父類(類似於寄生組合繼承)
class Per extends Person{
  constructor(age) {
    super('我是父類'); // !在子類的constructor第一行一定要加 super()
    this.age = age;
  }
}
let y = new Person('父類');
let q = new Per(12);


相關文章