JavaScript的ES5實現(xiàn)繼承的4種常用方法小結(jié)
前言
繼承是面向?qū)ο筌浖夹g(shù)當(dāng)中的一個概念。如果一個類別B“繼承自”另一個類別A,就把這個B稱為“A的子類”,而把A稱為“B的父類”也可以稱“A是B的超類”。
繼承的優(yōu)點是可以使得子類具有父類的屬性和方法,而不需要再次編寫相同的代碼,在子類繼承父類的同時,可以重新定義某些屬性,并重寫某些方法,即覆蓋父類的原有屬性和方法,使其獲得與父類不同的功能。
JavaScript
實現(xiàn)面向?qū)ο缶幊痰姆绞脚c傳統(tǒng)的面向?qū)ο笳Z言有所不同,它的面向?qū)ο筇匦灾饕谠秃驮玩湙C制,而不是基于類(盡管ES6
引入了class
關(guān)鍵字,但只是語法糖而已,底層依舊是基于原型的)。
接下來重點說說ES5的4種常用繼承方法
ES5實現(xiàn)的四種方式
1. 原型鏈繼承
原型鏈繼承其實就是讓子類的原型對象指向父類實例,當(dāng)子類實例找不到對應(yīng)的屬性和方法時,就會往它的原型上去找,從而實現(xiàn)對父類的屬性和方法的繼承
// 父類 function Person() { this.name = 'gan' } Person.prototype.getName = function () { return this.name } // 子類 function Student() { } Student.prototype = new Person() // 根據(jù)原型鏈的規(guī)則,順便綁定constructor 不影響繼承 Student.prototype.constructor = Student const student = new Student() console.log(student.name) // gan console.log(student.getName()) // gan
缺點
1.所有的Student實例都指向一個Person實例,這樣的話如果Person有一個引用類型的屬性,有一個student1實例改變了它,那么會影響所有的實例
function Person() { this.hobby = ['籃球', '足球'] } function Student() { } Student.prototype = new Person() const student1 = new Student() const student2 = new Student() student1.hobby.push('排球') console.log(student1.hobby) // [ '籃球', '足球', '排球' ] console.log(student2.hobby) // [ '籃球', '足球', '排球' ]
2.子類實例不能向父類構(gòu)造函數(shù)傳參,也就是沒有super()功能
2. 構(gòu)造函數(shù)繼承
構(gòu)造函數(shù)繼承就是在子類的構(gòu)造函數(shù)中執(zhí)行父類的構(gòu)造函數(shù),為父類構(gòu)造函數(shù)綁定子類的this,讓父類的屬性和方法都掛在子類上,這樣即避免每一個子類實例共享一個原型實例,并且這樣也可以向父類傳參
function Person() { this.name = 'gan' } Person.prototype.getName = function () { return this.name } function Student() { Person.apply(this, arguments) } const student = new Student() console.log(student.name) // gan
缺點
不能訪問父類的原型
console.log(student.getName) // undefined
3. 組合式繼承
組合式繼承其實就是結(jié)合了原型鏈繼承和構(gòu)造函數(shù)繼承兩種方式
function Person() { this.name = 'gan' } Person.prototype.getName = function () { return this.name } function Student() { Person.apply(this, arguments) } Student.prototype = new Person() Student.prototype.constructor = Student const student = new Student() console.log(student.getName()) // gan
缺點
每次創(chuàng)建子類實例時需要創(chuàng)建兩遍父類構(gòu)造函數(shù)(Person.apply和new Person),原型中會存在兩份相同的屬性和方法,雖然不影響繼承,但是不夠優(yōu)雅
4. 寄生式組合繼承
解決了執(zhí)行兩次父類構(gòu)造函數(shù)的問題,將指向父類實例改為指向父類原型
function Person() { this.name = 'gan' } Person.prototype.getName = function () { return this.name } function Student() { // 構(gòu)造函數(shù)繼承 Person.apply(this, arguments) } // Student.prototype = new Person() Student.prototype = Object.create(Person.prototype) Student.prototype.constructor = Student const student = new Student() console.log(student.getName()) // gan
這種方法是目前最優(yōu)的辦法
總結(jié)
- 最開始說到繼承,我們應(yīng)該先想到的是原型鏈繼承,子類的原型對象指向父類實例,但是它的缺點在于子類實例繼承父類引用類型時出現(xiàn)了問題以及實例不能向父類傳參的問題
- 接著就是構(gòu)造函數(shù)繼承,在子類的構(gòu)造函數(shù)中執(zhí)行父類的構(gòu)造函數(shù),為父類構(gòu)造函數(shù)綁定子類的this,但它也存在缺點就是不能繼承到父類原型鏈上的屬性和方法
- 后來就有了組合式繼承,是上面兩者的結(jié)合,問題就是每次都會執(zhí)行兩次父類構(gòu)造函數(shù)
- 最后就有了寄生式組合繼承
到此這篇關(guān)于JavaScript的ES5實現(xiàn)繼承的4種常用方法小結(jié)的文章就介紹到這了,更多相關(guān)JavaScript ES5繼承內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
微信小程序?qū)崿F(xiàn)給嵌套template模板傳遞數(shù)據(jù)的方式總結(jié)
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)給嵌套template模板傳遞數(shù)據(jù)的方式,結(jié)合實例形式總結(jié)分析了微信小程序嵌套template模板的定義、調(diào)用、參數(shù)傳遞及相關(guān)使用技巧,需要的朋友可以參考下2017-12-12javascript字符串拆分成單個字符相加和不超過10,求最終值
javascript字符串拆分成單個字符相加和不超過10,求最終值2008-09-09JavaScript中clientWidth,offsetWidth,scrollWidth的區(qū)別
這篇文章主要介紹了Element中clientWidth,offsetWidth,scrollWidth的區(qū)別,幫助大家更好的理解和使用JavaScript,感興趣的朋友可以了解下2021-01-01JavaScript 冒泡排序和選擇排序的實現(xiàn)代碼
本文通過實例代碼給大家介紹了js冒泡排序和選擇排序的實現(xiàn)代碼,代碼簡單易懂,非常不錯,具有參考借鑒價值,感興趣的朋友一起學(xué)習(xí)吧2016-09-09JavaScript實現(xiàn)網(wǎng)頁截屏的5種方法小結(jié)
本文主要介紹了JavaScript實現(xiàn)網(wǎng)頁截屏的5種方法小結(jié),感興趣的可以了解一下2009-10-10javascript實現(xiàn)隨機讀取數(shù)組的方法
這篇文章主要介紹了javascript實現(xiàn)隨機讀取數(shù)組的方法,涉及javascript隨機數(shù)及針對數(shù)組操作的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-08-08