Javascript的ES5,ES6的7種繼承詳解
眾所周知,在ES6
之前,前端是不存在類(lèi)的語(yǔ)法糖,所以不能像其他語(yǔ)言一樣用extends
關(guān)鍵字就搞定繼承關(guān)系,需要一些額外的方法來(lái)實(shí)現(xiàn)繼承。下面就介紹一些常用的方法,紅寶書(shū)已經(jīng)概括的十分全面了,所以本文基本就是對(duì)紅寶書(shū)繼承篇章的筆記和梳理。
原型鏈繼承
function Parent() { this.name = 'arzh' } Parent.prototype.getName = function () { console.log(this.name) } function Child() { } //主要精髓所在 Child.prototype = new Parent() Child.prototype.constructor = Child var arzhChild = new Child() arzhChild.getName() // 'arzh'
原型鏈繼承缺點(diǎn):
1.每個(gè)實(shí)例對(duì)引用類(lèi)型屬性的修改都會(huì)被其他的實(shí)例共享
function Parent() { this.names = ['arzh','arzh1']; } function Child() { } //主要精髓所在 Child.prototype = new Parent() Child.prototype.constructor = Child var arzhChild2 = new Child() arzhChild2.names.push('arzh2') console.log(arzhChild2.names) //[ 'arzh', 'arzh1', 'arzh2' ] var arzhChild3 = new Child() arzhChild3.names.push('arzh3') console.log(arzhChild3.names) //[ 'arzh', 'arzh1', 'arzh2', 'arzh3' ]
2.在創(chuàng)建Child
實(shí)例的時(shí)候,無(wú)法向Parent
傳參。這樣就會(huì)使Child
實(shí)例沒(méi)法自定義自己的屬性(名字)
借用構(gòu)造函數(shù)(經(jīng)典繼承)
function Parent() { this.names = ['arzh','arzh1'] } function Child() { Parent.call(this) } var arzhChild2 = new Child() arzhChild2.names.push('arzh2') console.log(arzhChild2.names) //[ 'arzh', 'arzh1', 'arzh2' ] var arzhChild3 = new Child() arzhChild3.names.push('arzh3') console.log(arzhChild3.names) //[ 'arzh', 'arzh1', 'arzh3' ]
優(yōu)點(diǎn):
- 解決了每個(gè)實(shí)例對(duì)引用類(lèi)型屬性的修改都會(huì)被其他的實(shí)例共享的問(wèn)題
- 子類(lèi)可以向父類(lèi)傳參
function Parent(name) { this.name = name } function Child(name) { Parent.call(this, name) } var arzhChild = new Child('arzh'); console.log(arzhChild.name); // arzh var arzhChild1 = new Child('arzh1'); console.log(arzhChild1.name); // arzh1
缺點(diǎn):
- 無(wú)法復(fù)用父類(lèi)的公共函數(shù)
- 每次子類(lèi)構(gòu)造實(shí)例都得執(zhí)行一次父類(lèi)函數(shù)
組合式繼承(原型鏈繼承和借用構(gòu)造函數(shù)合并)
function Parent(name) { this.name = name this.body = ['foot','hand'] } function Child(name, age) { Parent.call(this, name) this.age = age } Child.prototype = new Parent() Child.prototype.constructor = Child var arzhChild1 = new Child('arzh1', '18') arzhChild1.body.push('head1') console.log(arzhChild1.name,arzhChild1.age) //arzh1 18 console.log(arzhChild1.body) //[ 'foot', 'hand', 'head1' ] var arzhChild2 = new Child('arzh2', '20') arzhChild2.body.push('head2') console.log(arzhChild2.name,arzhChild2.age) //arzh2 20 console.log(arzhChild2.body) //[ 'foot', 'hand', 'head2' ]
優(yōu)點(diǎn):
- 解決了每個(gè)實(shí)例對(duì)引用類(lèi)型屬性的修改都會(huì)被其他的實(shí)例共享的問(wèn)題
- 子類(lèi)可以向父類(lèi)傳參
- 可實(shí)現(xiàn)父類(lèi)方法復(fù)用
缺點(diǎn):
- 需執(zhí)行兩次父類(lèi)構(gòu)造函數(shù),第一次是
Child.prototype = new Parent()
,第二次是Parent.call(this, name)
造成不必要的浪費(fèi)
原型式繼承
復(fù)制傳入的對(duì)象到創(chuàng)建對(duì)象的原型上,從而實(shí)現(xiàn)繼承
function createObj(o) { function F(){} F.prototype = o; return new F(); } var person = { name : 'arzh', body : ['foot','hand'] } var person1 = createObj(person) var person2 = createObj(person) console.log(person1) //arzh person1.body.push('head') console.log(person2) //[ 'foot', 'hand', 'head' ]
缺點(diǎn): 同原型鏈繼承一樣,每個(gè)實(shí)例對(duì)引用類(lèi)型屬性的修改都會(huì)被其他的實(shí)例共享
寄生式繼承
我們可以使用Object.create
來(lái)代替上述createObj
的實(shí)現(xiàn),原理基本上是一樣的。寄生式繼承其實(shí)就是在createObj
的內(nèi)部以某種形式來(lái)增強(qiáng)對(duì)象(這里的增強(qiáng)可以理解為添加對(duì)象的方法),最后返回增強(qiáng)之后的對(duì)象。
function createEnhanceObj(o) { //代替原型式繼承的createObj var clone = Object.create(o) clone.getName = function () { console.log('arzh') } return clone; }
通過(guò)createEnhanceObj
就可以在創(chuàng)建對(duì)象的時(shí)候,把對(duì)象方法也通過(guò)此種方式繼承。
缺點(diǎn): 同借用構(gòu)造函數(shù)一樣,無(wú)法復(fù)用父類(lèi)函數(shù),每次創(chuàng)建對(duì)象都會(huì)創(chuàng)建一遍方法
寄生組合式繼承
不需要為了子類(lèi)的原型而多new
了一次父類(lèi)的構(gòu)造函數(shù),如Child.prototype = new Parent()
只需要復(fù)制父類(lèi)原型的一個(gè)副本給子類(lèi)原型即可
function inheritPrototype(Parent, Child){ Child.prototype = Object.create(Parent.prototype) //創(chuàng)建父類(lèi)原型的一個(gè)副本,把副本賦值給子類(lèi)原型 Child.prototype.constructor = Child; } function Parent(name) { this.name = name } Parent.prototype.getName = function () { console.log(this.name) } function Child(color) { Parent.call(this, 'arzh') this.color = color } inheritPrototype(Parent, Child) var arzhChild = new Child('red') console.log(arzhChild.name) // 'arzh'
優(yōu)點(diǎn): 不必為了指定子類(lèi)型的原型而調(diào)用父類(lèi)型的構(gòu)造函數(shù)
ES6繼承
ES6
支持通過(guò)類(lèi)來(lái)實(shí)現(xiàn)繼承,方法比較簡(jiǎn)單,代碼如下
class Point { constructor(x, y) { this.x = x this.y = y } toString() { return this.x + '' + this.y } } class ColorPoint extends Point { constructor(x, y, color) { super(x, y) //調(diào)用父類(lèi)的constructor(x, y) this.color = color } toString() { return this.color + ' ' + super.toString() // 調(diào)用父類(lèi)的toString() } } var colorPoint = new ColorPoint('1', '2', 'red') console.log(colorPoint.toString()) // red 12
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
- JavaScript實(shí)現(xiàn)簡(jiǎn)易輪播圖最全代碼解析(ES5)
- 詳解JavaScript之ES5的繼承
- js定義類(lèi)的方法示例【ES5與ES6】
- 詳解vue-cli+es6引入es5寫(xiě)的js(兩種方法)
- JS實(shí)現(xiàn)集合的交集、補(bǔ)集、差集、去重運(yùn)算示例【ES5與ES6寫(xiě)法】
- JavaScript設(shè)計(jì)模式之原型模式分析【ES5與ES6】
- js es6系列教程 - 基于new.target屬性與es5改造es6的類(lèi)語(yǔ)法
- JavaScript ES5標(biāo)準(zhǔn)中新增的Array方法
- JS?ES5創(chuàng)建常量詳解
相關(guān)文章
Javascript數(shù)組Array基礎(chǔ)介紹
本文主要是給大家簡(jiǎn)單介紹了Array的相關(guān)基礎(chǔ)知識(shí),到這里也算是能對(duì)Array有更全面的理解了,希望大家能夠喜歡,后續(xù)我們將繼續(xù)介紹關(guān)于array的內(nèi)容。2016-03-03在javascript中創(chuàng)建對(duì)象的各種模式解析
下面小編就為大家?guī)?lái)一篇在javascript中創(chuàng)建對(duì)象的各種模式解析。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧2016-05-05JavaScript中setUTCMilliseconds()方法的使用詳解
這篇文章主要介紹了JavaScript中setUTCMilliseconds()方法的使用詳解,是JS入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-06-06javascript實(shí)現(xiàn)滑動(dòng)解鎖功能
這篇文章主要介紹了javascript實(shí)現(xiàn)滑動(dòng)解鎖功能的方法及示例,效果非常棒,需要的朋友可以參考下2014-12-12Javascript核心讀書(shū)有感之表達(dá)式和運(yùn)算符
這篇文章主要介紹了Javascript核心讀書(shū)有感之表達(dá)式和運(yùn)算符,十分詳細(xì),需要的朋友可以參考下2015-02-02整理JavaScript對(duì)DOM中各種類(lèi)型的元素的常用操作
這篇文章主要介紹了JavaScript對(duì)DOM中各種類(lèi)型的元素的常用操作整理,DOM操作是JavaScript程序的一大根本任務(wù),需要的朋友可以參考下2016-05-05