淺談JavaScript的幾種繼承實現(xiàn)方式
當前需求: 實現(xiàn) Student 繼承自 Person
如果手動實現(xiàn)繼承效果, Person和Student分別寫自己的屬性和方法, 兩個構(gòu)造函數(shù)之間沒有任何關聯(lián)
- 代碼編寫繁瑣
- 可維護性低
構(gòu)造函數(shù)Person
function Person(name, age, height, address) { this.age = age this.height = height this.address = address } Person.prototype.running = function() { console.log("running~") } Person.prototype.eating = function() { console.log("eating~") }
構(gòu)造函數(shù)Student
function Student(name, age, height, address, sno, score) { this.age = age this.height = height this.address = address this.sno = sno this.score = score } Student.prototype.running = function() { console.log("running~") } Student.prototype.eating = function() { console.log("eating~") } Student.prototype.studying = function() { console.log("studying~") }
內(nèi)存圖
希望滿足的條件功能
Student構(gòu)造函數(shù)滿足以下條件
- 能夠重寫繼承的方法, 但不修改Person原型上的方法.
- 能夠增加方法, 但不會影響Person原型上的方法.
Student構(gòu)建出的實例對象滿足以下條件
- 有name, age, height, address屬性, 并且擴充sno和score. 作為自己獨立的屬性.
- 繼承running, eating方法, 和Person實例對象的方法有相同的引用.
利用原形鏈實現(xiàn)方法的繼承
方式1: 子類原型指向父類原型
function Student(age, height, address, sno, score) { this.age = age this.height = height this.address = address this.sno = sno this.score = score } + Stuednt.prototype = Person.prototype
內(nèi)存圖
缺點
父類和子類共享通一個原型對象, 修改了任意一個, 另外一個也被修改
方式2 子類原型指向父類實例對象
function Student(sno, score) { this.sno = sno this.score = score } + var p = new Person() + Student.prototype = p
內(nèi)存圖
缺點
- 屬性放在了原型上, 無法通過打印查看.
- 創(chuàng)建的多個實例對象, 繼承的屬性不互相獨立, 一個實例對象修改屬性影響其他的實例對象
- 要new一個實例, 怪怪怪怪怪怪
借用構(gòu)造函數(shù)繼承
方式3 組合繼承
function Person(name, age, height, address) { this.name = name this.age = age this.height = height this.address = address } Person.prototype.running = ... function Student(age, height, address, sno, score) { + Person.call(this, age, height, address) this.sno = sno this.score = score } Student.prototype = new Person()
內(nèi)存圖
優(yōu)點
解決之前的硬性問題, 實例對象屬性獨立, 屬性放在對象內(nèi)而不是原型上.
缺點
- 調(diào)用兩次父類的構(gòu)造方法, 性能浪費
Student.prototype = new Person()
第一次Person.call(this)
第二次
- 調(diào)用兩次構(gòu)造方法, 導致子類創(chuàng)建的實例對象上, 保留了兩份父類的屬性
- 一份在實例對象的
__proto__
上, new時產(chǎn)生的 - 一份在實例對象上, 通過借用構(gòu)造方法call得到
- 一份在實例對象的
寄生式繼承
思路
屬性的繼承已經(jīng)解決, 通過Person.call(this)
解決.
方法的繼承未解決, 需要找到 Student.prototype = new Person()
的替代方案
思路1
var obj = {} obj.__proto__ = Person.prototype Student.prototype = obj // __proto__為瀏覽器增加的屬性, 解決瀏覽器兼容性問題可以改為 var obj = {} Object.setPrototypeOf(obj, Person.prototype) Student.prototype = obj
思路2
兼容所有瀏覽器 解決老版本瀏覽器不支持setPrototypeOf
function F() {} F.prototype = Person.prototype Student.prototype = new F()
思路3
Object.create()
傳入一個對象作為參數(shù), 并返回一個對象, 返回的對象的原型為傳入對象
var obj = Object.create(Person.prototype) Student.prototype = obj
最終 方式4: 寄生組合式繼承
// 工具函數(shù) // 創(chuàng)建對象的過程 function createObject(proto) { function F() {} F.prototype = proto return new F() } // 將Subtype和Supertype聯(lián)系在一起 // 寄生式函數(shù) function inherit(Subtype, Supertype) { Subtype.prototype = createObject(Supertype.prototype) Object.defineProperty(Subtype.prototype, "constructor", { enumerable: false, configurable: true, writable: true, value: Subtype }) } function Student(age, height, sno, score) { Person.call(this, age, height) this.sno = sno this.score = score } + inherit(Student, Person) // 使用方法 Student.prototype.studying = function() { console.log("studying") }
?? 使用Person.call
實現(xiàn)屬性的繼承
?? 使用inherit
實現(xiàn)方法的繼承
createObject
使Student.prototype指向Person的prototype, 但中間多一個構(gòu)造函數(shù)F(), 解決方式1 的問題Object.defineProperty
實現(xiàn)Student.prototype
的constructor
屬性指回Student構(gòu)造函數(shù).內(nèi)存圖
附: 擴充createObject
最初的設計思想, 是為了實現(xiàn)對象的繼承, 所以有了以下的代碼
createObject只能夠做到構(gòu)造一個有原型的空對象, 現(xiàn)在想要讓構(gòu)造的對象也有屬性
createInfo(proto, age, height) { const newObj = this.createObject(proto) newObj.age = age newObj.height = height return newObj }
到此這篇關于淺談JavaScript的幾種繼承實現(xiàn)方式的文章就介紹到這了,更多相關JavaScrip 繼承內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
JavaScript中數(shù)據(jù)類型轉(zhuǎn)換總結(jié)
在js中,數(shù)據(jù)類型轉(zhuǎn)換分為顯式數(shù)據(jù)類型轉(zhuǎn)換和隱式數(shù)據(jù)類型轉(zhuǎn)換。本文將對此進行介紹,具有一定的參考價值,需要的朋友一起來看下吧2016-12-12微信小程序定義和調(diào)用全局變量globalData的實現(xiàn)
這篇文章主要介紹了微信小程序定義和調(diào)用全局變量globalData的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-11-11Bootstrap 設置datetimepicker在屏幕上面彈出設置方法
datetimepicker默認是在輸入框下面彈出的,但是遇到輸入框在屏幕下面時,日期選擇框會有一部分在屏幕下面,顯示不了,因此需要能夠從上面彈出,下面小編給大家介紹下Bootstrap 設置datetimepicker在屏幕上面彈出的設置方法2017-03-03JavaScript 實現(xiàn)拖拽效果組件功能(兼容移動端)
這篇文章主要介紹了JavaScript 實現(xiàn)拖拽效果組件功能(兼容移動端),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-11-11JS實現(xiàn)頁面中所有img對象添加onclick事件及新窗口查看圖片的方法
這篇文章主要介紹了JS實現(xiàn)頁面中所有img對象添加onclick事件及新窗口查看圖片的方法,涉及JS頁面元素遍歷及屬性動態(tài)操作相關技巧,需要的朋友可以參考下2016-12-12