成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

JavaScript六種繼承方式

開發 前端
繼承是面向對象編程中又一非常重要的概念,JavaScript支持實現繼承,不支持接口繼承,實現繼承主要依靠原型鏈來實現的。

[[194938]]

繼承是面向對象編程中又一非常重要的概念,JavaScript支持實現繼承,不支持接口繼承,實現繼承主要依靠原型鏈來實現的。

原型鏈

首先得要明白什么是原型鏈,在一篇文章看懂proto和prototype的關系及區別中講得非常詳細

原型鏈繼承基本思想就是讓一個原型對象指向另一個類型的實例

  1. function SuperType() { 
  2.  
  3.   this.property = true 
  4.  
  5.  
  6. SuperType.prototype.getSuperValue = function () { 
  7.  
  8.   return this.property 
  9.  
  10.  
  11. function SubType() { 
  12.  
  13.   this.subproperty = false 
  14.  
  15.  
  16. SubType.prototype = new SuperType() 
  17.  
  18. SubType.prototype.getSubValue = function () { 
  19.  
  20.   return this.subproperty 
  21.  
  22.  
  23. var instance = new SubType() 
  24.  
  25. console.log(instance.getSuperValue()) // true  

代碼定義了兩個類型SuperType和SubType,每個類型分別有一個屬性和一個方法,SubType繼承了SuperType,而繼承是通過創建SuperType的實例,并將該實例賦給SubType.prototype實現的。

實現的本質是重寫原型對象,代之以一個新類型的實例,那么存在SuperType的實例中的所有屬性和方法,現在也存在于SubType.prototype中了。

我們知道,在創建一個實例的時候,實例對象中會有一個內部指針指向創建它的原型,進行關聯起來,在這里代碼SubType.prototype = new SuperType(),也會在SubType.prototype創建一個內部指針,將SubType.prototype與SuperType關聯起來。

所以instance指向SubType的原型,SubType的原型又指向SuperType的原型,繼而在instance在調用getSuperValue()方法的時候,會順著這條鏈一直往上找。

添加方法

在給SubType原型添加方法的時候,如果,父類上也有同樣的名字,SubType將會覆蓋這個方法,達到重新的目的。 但是這個方法依然存在于父類中。

記住不能以字面量的形式添加,因為,上面說過通過實例繼承本質上就是重寫,再使用字面量形式,又是一次重寫了,但這次重寫沒有跟父類有任何關聯,所以就會導致原型鏈截斷。

  1. function SuperType() { 
  2.  
  3.   this.property = true 
  4.  
  5.  
  6. SuperType.prototype.getSuperValue = function () { 
  7.  
  8.   return this.property 
  9.  
  10.  
  11. function SubType() { 
  12.  
  13.   this.subproperty = false 
  14.  
  15.  
  16. SubType.prototype = new SuperType() 
  17.  
  18. SubType.prototype = { 
  19.  
  20.   getSubValue:function () { 
  21.  
  22.    return this.subproperty 
  23.  
  24.   } 
  25.  
  26.  
  27. var instance = new SubType() 
  28.  
  29. console.log(instance.getSuperValue())  // error  

問題

單純的使用原型鏈繼承,主要問題來自包含引用類型值的原型。

  1. function SuperType() { 
  2.  
  3.   this.colors = ['red''blue''green'
  4.  
  5.  
  6. function SubType() { 
  7.  
  8.  
  9. SubType.prototype = new SuperType() 
  10.  
  11. var instance1 = new SubType() 
  12.  
  13. var instance2 = new SubType() 
  14.  
  15. instance1.colors.push('black'
  16.  
  17. console.log(instance1.colors)  // ["red""blue""green""black"
  18.  
  19. console.log(instance2.colors) // ["red""blue""green""black" 

在SuperType構造函數定義了一個colors屬性,當SubType通過原型鏈繼承后,這個屬性就會出現SubType.prototype中,就跟專門創建了SubType.prototype.colors一樣,所以會導致SubType的所有實例都會共享這個屬性,所以instance1修改colors這個引用類型值,也會反映到instance2中。

借用構造函數

此方法為了解決原型中包含引用類型值所帶來的問題。

這種方法的思想就是在子類構造函數的內部調用父類構造函數,可以借助apply()和call()方法來改變對象的執行上下文

  1. function SuperType() { 
  2.  
  3.   this.colors = ['red''blue''green'
  4.  
  5.  
  6. function SubType() { 
  7.  
  8.   // 繼承SuperType 
  9.  
  10.   SuperType.call(this) 
  11.  
  12.  
  13. var instance1 = new SubType() 
  14.  
  15. var instance2 = new SubType() 
  16.  
  17. instance1.colors.push('black'
  18.  
  19. console.log(instance1.colors)  // ["red""blue""green""black"
  20.  
  21. console.log(instance2.colors) // ["red""blue""green" 

在新建SubType實例是調用了SuperType構造函數,這樣以來,就會在新SubType對象上執行SuperType函數中定義的所有對象初始化代碼。

結果,SubType的每個實例就會具有自己的colors屬性的副本了。

傳遞參數

借助構造函數還有一個優勢就是可以傳遞參數

  1. function SuperType(name) { 
  2.  
  3.   this.name = name 
  4.  
  5.  
  6. function SubType() { 
  7.  
  8.   // 繼承SuperType 
  9.  
  10.   SuperType.call(this, 'Jiang'
  11.  
  12.   
  13.  
  14.   this.job = 'student' 
  15.  
  16.  
  17. var instance = new SubType() 
  18.  
  19. console.log(instance.name)  // Jiang 
  20.  
  21. console.log(instance.job)   // student  

問題

如果僅僅借助構造函數,方法都在構造函數中定義,因此函數無法達到復用

組合繼承(原型鏈+構造函數)

組合繼承是將原型鏈繼承和構造函數結合起來,從而發揮二者之長的一種模式。

思路就是使用原型鏈實現對原型屬性和方法的繼承,而通過借用構造函數來實現對實例屬性的繼承。

這樣,既通過在原型上定義方法實現了函數復用,又能夠保證每個實例都有它自己的屬性。

  1. function SuperType(name) { 
  2.  
  3.   this.name = name 
  4.  
  5.   this.colors = ['red''blue''green'
  6.  
  7.  
  8. SuperType.prototype.sayName = function () { 
  9.  
  10.   console.log(this.name
  11.  
  12.  
  13. function SubType(name, job) { 
  14.  
  15.   // 繼承屬性 
  16.  
  17.   SuperType.call(this, name
  18.  
  19.   
  20.  
  21.   this.job = job 
  22.  
  23.  
  24. // 繼承方法 
  25.  
  26. SubType.prototype = new SuperType() 
  27.  
  28. SubType.prototype.constructor = SuperType 
  29.  
  30. SubType.prototype.sayJob = function() { 
  31.  
  32.   console.log(this.job) 
  33.  
  34.  
  35. var instance1 = new SubType('Jiang''student'
  36.  
  37. instance1.colors.push('black'
  38.  
  39. console.log(instance1.colors) //["red""blue""green""black"
  40.  
  41. instance1.sayName() // 'Jiang' 
  42.  
  43. instance1.sayJob()  // 'student' 
  44.  
  45. var instance2 = new SubType('J''doctor'
  46.  
  47. console.log(instance2.colors) // //["red""blue""green"
  48.  
  49. instance2.sayName()  // 'J' 
  50.  
  51. instance2.sayJob()  // 'doctor'  

這種模式避免了原型鏈和構造函數繼承的缺陷,融合了他們的優點,是最常用的一種繼承模式。

原型式繼承

借助原型可以基于已有的對象創建新對象,同時還不必因此創建自定義類型。

  1. function object(o) { 
  2.  
  3.   function F() {} 
  4.  
  5.   F.prototype = o 
  6.  
  7.   return new F() 
  8.  
  9.  

在object函數內部,先創建一個臨時性的構造函數,然后將傳入的對象作為這個構造函數的原型,***返回這個臨時類型的一個新實例。

本質上來說,object對傳入其中的對象執行了一次淺復制。

  1. var person = { 
  2.  
  3.   name'Jiang'
  4.  
  5.   friends: ['Shelby''Court'
  6.  
  7.  
  8. var anotherPerson = object(person) 
  9.  
  10. console.log(anotherPerson.friends)  // ['Shelby''Court' 

這種模式要去你必須有一個對象作為另一個對象的基礎。

在這個例子中,person作為另一個對象的基礎,把person傳入object中,該函數就會返回一個新的對象。

這個新對象將person作為原型,所以它的原型中就包含一個基本類型和一個引用類型。

所以意味著如果還有另外一個對象關聯了person,anotherPerson修改數組friends的時候,也會體現在這個對象中。

Object.create()方法

ES5通過Object.create()方法規范了原型式繼承,可以接受兩個參數,一個是用作新對象原型的對象和一個可選的為新對象定義額外屬性的對象,行為相同,基本用法和上面的object一樣,除了object不能接受第二個參數以外。

  1. var person = { 
  2.  
  3.   name'Jiang'
  4.  
  5.   friends: ['Shelby''Court'
  6.  
  7.  
  8. var anotherPerson = Object.create(person) 
  9.  
  10. console.log(anotherPerson.friends)  // ['Shelby''Court' 

寄生式繼承

寄生式繼承的思路與寄生構造函數和工廠模式類似,即創建一個僅用于封裝繼承過程的函數。

  1. function createAnother(o) { 
  2.  
  3.   var clone = Object.create(o) // 創建一個新對象 
  4.  
  5.   clone.sayHi = function() { // 添加方法 
  6.  
  7.     console.log('hi'
  8.  
  9.   } 
  10.  
  11.   return clone  // 返回這個對象 
  12.  
  13.  
  14. var person = { 
  15.  
  16.   name'Jiang' 
  17.  
  18.  
  19. var anotherPeson = createAnother(person) 
  20.  
  21. anotherPeson.sayHi()  

基于person返回了一個新對象anotherPeson,新對象不僅擁有了person的屬性和方法,還有自己的sayHi方法。

在主要考慮對象而不是自定義類型和構造函數的情況下,這是一個有用的模式。

寄生組合式繼承

在前面說的組合模式(原型鏈+構造函數)中,繼承的時候需要調用兩次父類構造函數。

父類

  1. function SuperType(name) { 
  2.  
  3.   this.name = name 
  4.  
  5.   this.colors = ['red''blue''green'
  6.  
  7.  

***次在子類構造函數中

  1. function SubType(name, job) { 
  2.  
  3.   // 繼承屬性 
  4.  
  5.   SuperType.call(this, name
  6.  
  7.   
  8.  
  9.   this.job = job 
  10.  
  11.  

第二次將子類的原型指向父類的實例

  1. // 繼承方法 
  2.  
  3. SubType.prototype = new SuperType()  

當使用var instance = new SubType()的時候,會產生兩組name和color屬性,一組在SubType實例上,一組在SubType原型上,只不過實例上的屏蔽了原型上的。

使用寄生式組合模式,可以規避這個問題。

這種模式通過借用構造函數來繼承屬性,通過原型鏈的混成形式來繼承方法。

基本思路:不必為了指定子類型的原型而調用父類的構造函數,我們需要的無非就是父類原型的一個副本。

本質上就是使用寄生式繼承來繼承父類的原型,在將結果指定給子類型的原型。

  1. function inheritPrototype(subType, superType) { 
  2.  
  3.   var prototype = Object.create(superType.prototype) 
  4.  
  5.   prototype.constructor = subType 
  6.  
  7.   subType.prototype = prototype 
  8.  
  9.  

該函數實現了寄生組合繼承的最簡單形式。

這個函數接受兩個參數,一個子類,一個父類。

***步創建父類原型的副本,第二步將創建的副本添加constructor屬性,第三部將子類的原型指向這個副本。

  1. function SuperType(name) { 
  2.  
  3.   this.name = name 
  4.  
  5.   this.colors = ['red''blue''green'
  6.  
  7.  
  8. SuperType.prototype.sayName = function () { 
  9.  
  10.   console.log(this.name
  11.  
  12.  
  13. function SubType(name, job) { 
  14.  
  15.   // 繼承屬性 
  16.  
  17.   SuperType.call(this, name
  18.  
  19.   
  20.  
  21.   this.job = job 
  22.  
  23.  
  24. // 繼承 
  25.  
  26. inheritPrototype(SubType, SuperType) 
  27.  
  28. var instance = new SubType('Jiang''student'
  29.  
  30. instance.sayName()  

補充:直接使用Object.create來實現,其實就是將上面封裝的函數拆開,這樣演示可以更容易理解。

  1. function SuperType(name) { 
  2.  
  3.   this.name = name 
  4.  
  5.   this.colors = ['red''blue''green'
  6.  
  7.  
  8. SuperType.prototype.sayName = function () { 
  9.  
  10.   console.log(this.name
  11.  
  12.  
  13. function SubType(name, job) { 
  14.  
  15.   // 繼承屬性 
  16.  
  17.   SuperType.call(this, name
  18.  
  19.   
  20.  
  21.   this.job = job 
  22.  
  23.  
  24. // 繼承 
  25.  
  26. SubType.prototype = Object.create(SuperType.prototype) 
  27.  
  28. // 修復constructor 
  29.  
  30. SubType.prototype.constructor = SubType 
  31.  
  32. var instance = new SubType('Jiang''student'
  33.  
  34. instance.sayName()  

ES6新增了一個方法,Object.setPrototypeOf,可以直接創建關聯,而且不用手動添加constructor屬性。 

  1. // 繼承 
  2.  
  3. Object.setPrototypeOf(SubType.prototype, SuperType.prototype) 
  4.  
  5. console.log(SubType.prototype.constructor === SubType) // true  
責任編輯:龐桂玉 來源: 前端大全
相關推薦

2023-10-30 11:53:37

繼承JS父類

2009-02-11 09:46:00

ASON網絡演進

2025-02-27 00:00:30

SpringJava方式

2022-03-23 12:55:50

農業物聯網

2023-05-10 13:58:13

服務限流系統

2021-01-08 10:52:22

物聯網萬物互聯IoT,Interne

2019-05-16 13:00:18

異步編程JavaScript回調函數

2020-07-31 11:12:39

安全威脅網絡攻擊網絡安全

2020-04-27 09:00:00

雙因素認證身份認證生物識別

2022-01-14 10:34:50

黑客隱藏蹤跡網絡安全

2018-08-03 16:40:06

前端前端框架微服務

2019-05-15 08:00:00

vue組件間通信前端

2010-09-13 18:02:46

2025-01-21 10:04:40

Java并發阻塞隊列

2024-04-19 09:26:43

人工智能Llama 3 模型Meta

2025-04-29 08:21:30

ANRAndroidUI

2025-05-15 07:15:00

AI智能勞動力GenAI

2012-08-22 10:32:34

2024-05-30 08:51:28

Spring數據分布式

2011-03-10 14:19:56

JavaScript
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产免费看 | 69福利影院 | 欧美一区二区在线 | 久久99精品久久久久久国产越南 | 精品日韩一区二区 | 91精品在线播放 | 国产中文区二幕区2012 | www.国产精 | 欧美日韩国产精品一区二区 | 日韩欧美专区 | 欧美中文字幕一区二区三区亚洲 | 亚洲一区中文字幕 | 久久国产精品免费一区二区三区 | 欧美色999| 色婷婷av久久久久久久 | 国产成人91视频 | 久日精品| 欧美中文字幕一区二区三区亚洲 | 亚洲av毛片 | av黄色在线观看 | 国产精品久久国产精品99 | 精品国产乱码久久久久久丨区2区 | 欧美日韩视频在线 | 亚洲三级av | 一道本不卡视频 | 四季久久免费一区二区三区四区 | 亚洲在线成人 | 一区二区三区日本 | 久久亚洲春色中文字幕久久久 | 欧美11一13sex性hd | 美女艹b | 九九伊人sl水蜜桃色推荐 | 中文字幕一区二区三区在线观看 | 婷婷激情在线 | 青青草视频免费观看 | a级片在线观看 | 精品国产免费一区二区三区五区 | 天天综合天天 | 精品久| 亚洲日韩中文字幕一区 | 在线91|