中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JavaScript中常見的七種繼承怎么實現

發布時間:2023-03-08 09:20:34 來源:億速云 閱讀:109 作者:iii 欄目:開發技術

本篇內容主要講解“JavaScript中常見的七種繼承怎么實現”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“JavaScript中常見的七種繼承怎么實現”吧!

1. 原型鏈繼承

原型鏈繼承是 JavaScript 中一種基于原型的繼承方式,它通過將一個構造函數的實例作為另一個構造函數的原型,從而實現繼承。具體來說,就是在子類的構造函數中通過 Child.prototype = new Parent() 的方式來繼承父類的屬性和方法。

以下是一個實現原型鏈繼承的示例代碼:

// 定義父類構造函數functionParent(name) {
  this.name = name;
}
 
// 父類原型上的方法Parent.prototype.sayName = function() {
  console.log('My name is ' + this.name);
}
 
// 定義子類構造函數functionChild(name, age) {
  this.age = age;
}
 
// 將子類的原型設置為父類的實例Child.prototype = newParent();
 
// 子類原型上的方法Child.prototype.sayAge = function() {
  console.log('I am ' + this.age + ' years old');
}
 
// 創建子類實例var child = newChild('Tom', 10);
 
// 調用子類實例的方法
child.sayName(); // My name is Tom
child.sayAge(); // I am 10 years old

在上面的示例代碼中,我們首先定義了一個父類構造函數 Parent,并在其原型上定義了一個方法 sayName。然后我們定義了一個子類構造函數 Child,并通過將子類的原型設置為父類的實例來實現繼承。最后我們創建了一個子類實例 child,并調用其方法來驗證繼承是否成功。

優點:

  • 簡單易懂:原型鏈繼承是一種簡單的繼承方式,易于理解和實現。

  • 父類方法更新會自動同步到子類實例:由于子類實例的原型指向父類實例,所以父類的方法更新會自動同步到子類實例中。

  • 可以重用父類方法:由于子類實例可以訪問父類的原型,因此可以重用父類的方法,從而減少代碼量。

缺點:

  • 所有子類實例共享原型對象:由于所有子類實例的原型都指向同一個對象,因此一個實例對原型對象的修改會影響到其他實例。

  • 無法向父類構造函數傳遞參數:原型鏈繼承無法向父類構造函數傳遞參數,因此子類實例無法向父類構造函數傳遞參數,也無法對父類實例進行初始化。

  • 無法實現多繼承:由于JavaScript中一個對象只能有一個原型對象,因此原型鏈繼承無法實現多繼承。

2. 借用構造函數繼承

JavaScript中的借用構造函數繼承是一種通過調用父類構造函數來實現繼承的方式。這種繼承方式有以下特點:

子類實例擁有了父類構造函數中定義的屬性和方法。

子類實例與父類實例之間不存在原型鏈的關系,因此可以避免共享原型對象帶來的問題。

子類無法重用父類原型對象上的方法。

以下是一個借用構造函數繼承的示例代碼:

functionAnimal(name) {
  this.name = name;
}
 
Animal.prototype.sayName = function() {
  console.log('My name is ' + this.name);
}
 
functionDog(name, age) {
  Animal.call(this, name); // 借用Animal構造函數,并將this指向Dog實例this.age = age;
}
 
let dog1 = newDog('旺財', 2);
let dog2 = newDog('小白', 1);
 
console.log(dog1.name); // '旺財'console.log(dog2.age); // 1
dog1.sayName(); // TypeError: dog1.sayName is not a function

在上面的代碼中,Dog類通過調用Animal構造函數來實現繼承,從而擁有了Animal類中定義的屬性和方法。由于子類實例與父類實例之間不存在原型鏈的關系,因此修改一個實例的屬性不會影響到其他實例。

但是需要注意的是,由于子類實例無法訪問父類原型對象上的方法,因此在上面的代碼中,dog1實例調用sayName()方法會報錯。如果需要在子類中重用父類原型對象上的方法,可以考慮使用組合繼承或寄生組合式繼承。

優點:

  • 可以向父類構造函數傳遞參數:借用構造函數繼承可以向父類構造函數傳遞參數,從而可以對父類實例進行初始化。

  • 避免了原型對象共享的問題:由于借用構造函數繼承創建了一個新的對象,因此避免了原型對象共享的問題。

  • 可以實現多繼承:由于JavaScript中可以在一個構造函數中調用多個構造函數,因此可以通過借用構造函數繼承來實現多繼承。

缺點:

  • 無法重用父類方法:由于借用構造函數繼承創建了一個新的對象,因此無法重用父類的方法。

  • 父類方法更新不會自動同步到子類實例:由于借用構造函數繼承創建了一個新的對象,因此父類的方法更新不會自動同步到子類實例中。

  • 無法訪問父類原型上的屬性和方法:由于借用構造函數繼承只繼承了父類的實例屬性和方法,因此無法訪問父類原型上的屬性和方法。如果需要訪問父類原型上的屬性和方法,仍然需要通過將子類的原型指向父類的實例來實現。

3. 組合繼承

JavaScript中的組合繼承是一種結合借用構造函數和原型鏈繼承的方式,它的核心思想是使用借用構造函數繼承實例屬性和方法,使用原型鏈繼承共享屬性和方法。

以下是一個組合繼承的示例代碼:

functionAnimal(name) {
  this.name = name;
}
 
Animal.prototype.sayName = function() {
  console.log('My name is ' + this.name);
}
 
functionDog(name, age) {
  Animal.call(this, name); // 借用Animal構造函數,并將this指向Dog實例this.age = age;
}
 
Dog.prototype = newAnimal(); // 原型鏈繼承Animal類的屬性和方法Dog.prototype.constructor = Dog; // 修復構造函數指向let dog1 = newDog('旺財', 2);
let dog2 = newDog('小白', 1);
 
console.log(dog1.name); // '旺財'console.log(dog2.age); // 1
dog1.sayName(); // 'My name is 旺財'

在上面的代碼中,Dog類通過借用Animal構造函數繼承實例屬性和方法,通過原型鏈繼承Animal類的屬性和方法。由于子類實例與父類實例之間不存在原型鏈的關系,因此修改一個實例的屬性不會影響到其他實例。同時,子類實例可以重用父類原型對象上的方法。

需要注意的是,由于在上面的代碼中通過Dog.prototype = new Animal()創建了一個新的Animal實例,因此在創建Dog類時會調用兩次Animal構造函數,造成了性能上的浪費。可以使用寄生組合式繼承來解決這個問題。

具體來說,組合繼承通過將父類的構造函數借用到子類中,從而實現了父類屬性的繼承,同時通過將子類的原型設置為一個新的父類實例,從而實現了父類方法的繼承。這種繼承方式具有以下優缺點:

優點:

  • 父類的構造函數可以傳遞參數,并且不會影響到其他實例。

  • 子類實例可以訪問父類原型對象上的方法,可以重用父類的方法。

  • 可以實現多繼承。

  • 實現簡單、易于理解。

缺點:

  • 子類實例會同時擁有自己的屬性和方法,以及父類的屬性和方法,可能導致內存浪費和屬性名沖突的問題。

  • 在創建子類實例時,父類構造函數會被調用兩次,可能會影響性能。

4. 原型式繼承

JavaScript中的原型式繼承是一種基于已有對象創建新對象的繼承方式,它利用了對象的動態特性,通過封裝一個函數來實現繼承。該函數接收一個用作新對象原型的對象作為參數,并返回一個新對象,從而實現了繼承。該方式與借用構造函數繼承類似,但它并不涉及到構造函數和實例的概念。原型式繼承具有以下特點:

基于已有對象創建新對象。

可以使用Object.create()方法實現。

可以將一個對象作為另一個對象的原型對象。

可以使用原型對象的屬性和方法,但不會影響到原型對象本身。

下面是一個使用原型式繼承的示例代碼:

let animal = {
  type: 'animal',
  sayType: function() {
    console.log('I am a ' + this.type);
  }
};
 
let dog = Object.create(animal); // 使用animal對象作為dog對象的原型
dog.type = 'dog';
 
dog.sayType(); // 'I am a dog'

在上面的代碼中,animal對象擁有一個type屬性和一個sayType方法,dog對象通過使用animal對象作為原型對象來實現了繼承。因此,dog對象可以使用原型對象的屬性和方法,但并不會影響到原型對象本身。此外,通過給dog對象添加一個type屬性,也可以覆蓋原型對象的type屬性,實現對父對象屬性的重寫。原型式繼承的優點在于可以方便地實現對象的復用,但也容易導致對象之間的耦合,不易于維護。

具體來說,它通過創建一個空對象,并將其原型設置為一個已有對象,然后向這個空對象中添加屬性和方法來實現繼承。原型式繼承具有以下優缺點:

優點:

  • 簡單、易于理解和實現。

  • 可以基于一個對象創建多個對象,實現對象復用。

缺點:

  • 父對象的引用屬性會被所有子對象共享,因此子對象的修改會影響到其他子對象。

  • 子對象無法像傳統的類繼承一樣判斷自己是否是父對象的實例。

  • 無法實現多繼承。

5. 寄生式繼承

JavaScript中的寄生式繼承是一種基于已有對象創建新對象的繼承方式,類似于原型式繼承。它的主要區別是,在新創建的對象上增加一個方法,而這個方法的作用是以某種方式增強對象,然后返回這個對象。這種繼承方式得名于“寄生”,因為增強對象的方法通常是基于已有的對象進行“寄生”而得名。

寄生式繼承的優點是可以封裝繼承過程,并且可以向對象中添加一些額外的屬性和方法。但是和原型式繼承一樣,也存在父對象的引用屬性被所有子對象共享、無法判斷實例是否是父對象的實例等問題。

以下是一個使用寄生式繼承的示例代碼:

functioncreateAnimal(type) {
  let animal = {
    type: type,
    sayType: function() {
      console.log('I am a ' + this.type);
    }
  };
  // 基于animal對象進行寄生增強let dog = Object.create(animal);
  dog.bark = function() {
    console.log('woof woof');
  };
  return dog;
}
 
let myDog = createAnimal('canine');
myDog.sayType(); // 'I am a canine'
myDog.bark(); // 'woof woof'

在上面的代碼中,我們定義了一個名為createAnimal的函數,用于創建一個繼承自animal對象的新對象。我們在這個新對象上增加了一個bark方法,用于讓對象發出叫聲。最后,我們返回這個新對象,并將它賦值給myDog變量。通過這樣的方式,我們成功地實現了寄生式繼承。

具體來說,它在原型式繼承的基礎上增加了一個包裝函數,該函數用于封裝繼承過程中的一些增強行為。寄生式繼承具有以下優缺點:

優點:

  • 簡單、易于理解和實現。

  • 可以基于一個對象創建多個對象,實現對象復用。

  • 可以在不修改原對象的情況下,對繼承過程進行一些增強,例如添加新的屬性和方法。

缺點:

  • 父對象的引用屬性會被所有子對象共享,因此子對象的修改會影響到其他子對象。

  • 子對象無法像傳統的類繼承一樣判斷自己是否是父對象的實例。

  • 增強行為可能會帶來一定的性能開銷。

  • 可能會導致代碼的可讀性降低。

6. 寄生式組合繼承

JavaScript中的寄生式組合繼承是一種結合了組合繼承和寄生式繼承的繼承方式。具體來說,它在組合繼承的基礎上,通過寄生式繼承來解決組合繼承中重復調用父構造函數的問題。

下面是一個使用寄生式組合繼承的示例代碼:

functionAnimal(name) {
  this.name = name;
  this.type = 'mammal';
}
 
Animal.prototype.sayName = function() {
  console.log('My name is ' + this.name);
};
 
functionDog(name, breed) {
  Animal.call(this, name);
  this.breed = breed;
}
 
// 使用寄生式繼承繼承Animal.prototypeDog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
 
Dog.prototype.sayBreed = function() {
  console.log('I am a ' + this.breed);
};
 
let myDog = newDog('Max', 'Golden Retriever');
myDog.sayName(); // 'My name is Max'
myDog.sayBreed(); // 'I am a Golden Retriever'

在上面的代碼中,我們定義了Animal和Dog兩個構造函數,其中Animal構造函數定義了一個name屬性和一個sayName()方法,Dog構造函數在Animal的基礎上添加了一個breed屬性和一個sayBreed()方法。為了實現寄生式組合繼承,我們使用Object.create()方法基于Animal.prototype創建了一個新的對象,并將其賦值給Dog.prototype,從而使得Dog.prototype的原型鏈指向了Animal.prototype。同時,我們還將Dog.prototype的constructor屬性設置為Dog,以保證繼承鏈的完整性。最后,我們通過調用Animal構造函數并將this指向Dog對象,實現了對Animal屬性的繼承。通過這種方式,我們既避免了組合繼承中重復調用父構造函數的問題,又保留了寄生式繼承的靈活性,實現了一個高效而且靈活的繼承方式。

優點:

  • 實現了屬性和方法的完整繼承。

  • 避免了組合繼承中重復調用父類構造函數的問題,提高了性能。

  • 可以在不修改原對象的情況下,對繼承過程進行一些增強,例如添加新的屬性和方法。

缺點:

  • 增加了一層包裝函數,可能會帶來一定的性能開銷。

  • 可能會導致代碼的可讀性降低。

7. class繼承

在ES6及以上的版本中,JavaScript引入了class關鍵字,用于定義類,從而實現面向對象編程。class繼承是一種通過類來實現繼承的方式,它使用extends關鍵字來指定父類,并通過super關鍵字來調用父類的構造函數和方法。

以下是一個使用class繼承的示例代碼:

classAnimal {
  constructor(type) {
    this.type = type;
  }
 
  sayType() {
    console.log('I am a ' + this.type);
  }
}
 
classDogextendsAnimal {
  constructor(type, name) {
    super(type);
    this.name = name;
  }
 
  sayName() {
    console.log('My name is ' + this.name);
  }
}
 
let dog = newDog('canine', 'Fido'); // 創建一個新的Dog對象
 
dog.sayType(); // 'I am a canine'
dog.sayName(); // 'My name is Fido'

在上面的代碼中,我們首先定義了一個Animal類,它包含一個構造函數和一個sayType()方法。然后我們通過extends關鍵字來指定Dog類的父類為Animal,并在Dog類的構造函數中通過super關鍵字來調用Animal構造函數,并實現了sayName()方法。最后,我們創建一個新的Dog對象,并調用它的方法來測試繼承是否成功。

優點:

  • 代碼可讀性高,更易于理解和維護。

  • 語法簡潔,可以更快地編寫代碼。

  • 可以使用現代JavaScript特性,如箭頭函數、解構賦值等。

缺點:

  • 與ES5及以下版本的JavaScript不兼容。

  • 需要編譯才能運行在低版本瀏覽器中。

  • 某些開發者可能認為使用類和繼承違背了JavaScript的本質。

總體來說,class繼承是一種非常方便的繼承方式,特別是在面向對象編程中,能夠大大簡化代碼的編寫和維護。但在一些特定情況下,其他繼承方式可能更為適合。

到此,相信大家對“JavaScript中常見的七種繼承怎么實現”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

波密县| 娄烦县| 沂水县| 余江县| 武隆县| 福泉市| 靖远县| 福安市| 阿荣旗| 隆昌县| 浦城县| 湄潭县| 蕲春县| 南开区| 建始县| 巴林左旗| 咸阳市| 上高县| 河间市| 高州市| 皮山县| 舒兰市| 瑞金市| 安乡县| 肇庆市| 柳江县| 泰宁县| 东山县| 车险| 格尔木市| 怀柔区| 太白县| 阳朔县| 柘荣县| 财经| 贡嘎县| 开平市| 敖汉旗| 常宁市| 苏州市| 永德县|