欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解JavaScript實(shí)現(xiàn)繼承的五種經(jīng)典方式(附圖解)

 更新時間:2023年08月11日 09:42:36   作者:自律版Zz  
JavaScript中的繼承是一種機(jī)制,通過它可以創(chuàng)建一個對象,該對象可以享有另一個對象的屬性和方法,本文將詳細(xì)的為大家介紹實(shí)現(xiàn)繼承的五種經(jīng)典方式,感興趣的小伙伴跟著小編一起來看看吧

前言

  • 在 JavaScript 中,實(shí)現(xiàn)繼承的幾種常見方式包括:
      1. 原型鏈繼承: 此種方式也有兩種方式
      • 1.1 共享同一個父類實(shí)例
      • 1.2 繞過父類實(shí)例,共享同一個類型原型
      1. 構(gòu)造函數(shù)繼承(借用構(gòu)造函數(shù))
      1. 組合繼承
      1. 原型式繼承
      1. ES6 類繼承

原型鏈繼承

原型鏈繼承-共享同一個父類實(shí)例

這是 JavaScript 最早的繼承方式,通過將子類的原型對象指向父類的實(shí)例,實(shí)現(xiàn)子類繼承父類的屬性和方法。但它有一個缺點(diǎn),就是所有子類實(shí)例共享同一個父類實(shí)例。

function Parent() {
  this.property = "parentProperty";
}
Parent.prototype.say = function () {
  console.log("Parent say");
};
function Child() {
  this.childProperty = "childProperty";
}
// 修改 Child 的 prototype 屬性指向 Parent 實(shí)例對象,那么 Child 實(shí)例對象的 __proto__ 就會指向其構(gòu)造函數(shù) Child 的 prototype 屬性(即Parent 實(shí)例對象)
// 修改了 Child.prototype 的指向后,那么原來 Child.prototype 指向的對象由于被沒有引用,就會被回收。
Child.prototype = new Parent();
const childInstance = new Child();
console.log(childInstance.property); // 輸出 'parentProperty'
childInstance.say();

下圖是代碼圖解:

48.png

上面的代碼看似沒有問題,但其實(shí)還是存在缺陷:

console.log(Child.prototype.constructor); // 輸出:[Function: Parent], 即是 Parent 構(gòu)造函數(shù),這是由于 Child.prototype 自身沒有,就會沿著 __proto__ 尋找,因此找到 Parent。這明顯是不對的
console.log(Child.prototype.constructor === Child); // 輸出:false, 這明顯也是不對的

因此我們需要再修改 Child.prototype 的指向之后(即代碼 Child.prototype = new Parent(); ),需要同時修改 Child.prototype.constructor 的指向:

Child.prototype = new Parent();
+Child.prototype.constructor = Child;
  • 后續(xù)代碼也是同理!

原型鏈繼承-繞過父類實(shí)例,共享同一個父類的原型

function Parent() {
  this.property = "parentProperty";
}
Parent.prototype.say = function () {
  console.log("Parent say");
};
function Child() {
  Parent.call(this);
  this.childProperty = "childProperty";
}
// 方式一:直接指向
// Child.prototype.__proto__ = Parent.prototype;
// 方式二:使用 Object.create(),這是 es5 的方法
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
let childInstance = new Child();
console.log(childInstance.property);
childInstance.say();

下圖是代碼圖解:

51.png

構(gòu)造函數(shù)繼承(借用構(gòu)造函數(shù))

這種方式通過在子類構(gòu)造函數(shù)中調(diào)用父類構(gòu)造函數(shù),實(shí)現(xiàn)繼承屬性。這樣每個子類實(shí)例都擁有獨(dú)立的屬性副本,但無法繼承父類原型上的方法。

function Parent() {
  this.property = "parentProperty";
}
Parent.prototype.say = function () {
  console.log("Parent say");
};
function Child() {
  Parent.call(this);
  this.childProperty = "childProperty";
}
const childInstance = new Child();
console.log(childInstance.property); // 輸出 'parentProperty'
// childInstance.say() // 報錯:childInstance.say is not a function

下圖是代碼圖解:

49.png

組合繼承

組合繼承結(jié)合了原型鏈繼承和構(gòu)造函數(shù)繼承,通過在子類構(gòu)造函數(shù)中調(diào)用父類構(gòu)造函數(shù),然后設(shè)置子類的原型為一個父類實(shí)例,實(shí)現(xiàn)了既能繼承屬性又能繼承方法。

function Parent() {
  this.property = "parentProperty";
}
Parent.prototype.say = function () {
  console.log("Parent say");
};
function Child() {
  Parent.call(this);
  this.childProperty = "childProperty";
}
Child.prototype = new Parent();
// 注意:修改其原型對象之后,同時必須得修改 constructor 的指向
Child.prototype.constructor = Child;
const childInstance = new Child();
console.log(childInstance.property); // 輸出 'parentProperty'
childInstance.say();

52.png

原型式繼承

這種繼承方式創(chuàng)建一個臨時的構(gòu)造函數(shù),將這個構(gòu)造函數(shù)的原型指向父構(gòu)造函數(shù)的原型,再將子構(gòu)造函數(shù)的原型指向該構(gòu)造函數(shù)的實(shí)例,從而實(shí)現(xiàn)繼承。

function mockExtend(Parent, Child) {
  function Fn() {}
  /**
   * 1. 修改了 Fn.prototype 的指向后,那么原來的 Fn.prototype 沒有被引用,則會被回收
   * 2. 那么Fn的實(shí)例對象的 __proto__ 就指向其構(gòu)造函數(shù)的 prototype
   */
  Fn.prototype = Parent.prototype;
  Child.prototype = new Fn();
  // 注意:修改了原型對象之后,同時必須得修改 constructor 的指向
  Child.prototype.constructor = Child;
}
// =============================== 使用 ==================================
function Parent() {
  this.property = "parentProperty";
}
Parent.prototype.say = function () {
  console.log("Parent say");
};
function Child() {
  Parent.call(this);
  this.childProperty = "childProperty";
}
mockExtend(Parent, Child);
const childInstance = new Child();
console.log(childInstance.property);
childInstance.say();

下圖是代碼圖解:

50.png

ES6 類繼承

ES6 引入了 class 關(guān)鍵字,使繼承更加易讀和易用。通過 extends 關(guān)鍵字,一個類可以繼承另一個類的屬性和方法。

class Parent {
  constructor() {
    this.property = "parentProperty";
  }
  say() {
    console.log("Parent say");
  }
}
class Child extends Parent {
  constructor() {
    super();
    this.childProperty = "childProperty";
  }
}
const childInstance = new Child();
console.log(childInstance.property); // 輸出 'parentProperty'
childInstance.say();

到此這篇關(guān)于詳解JavaScript實(shí)現(xiàn)繼承的五種經(jīng)典方式(附圖解)的文章就介紹到這了,更多相關(guān)JavaScript實(shí)現(xiàn)繼承方式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論