摘要:中實(shí)現(xiàn)繼承的方式有很多種,一般都是通過(guò)原型鏈和構(gòu)造函數(shù)來(lái)實(shí)現(xiàn)。下面對(duì)各種實(shí)現(xiàn)方式進(jìn)行分析,總結(jié)各自的優(yōu)缺點(diǎn)。一原型繼承通過(guò)改變?cè)蛯?duì)象實(shí)現(xiàn)繼承保持構(gòu)造函數(shù)和原型對(duì)象的完整性說(shuō)明是繼承而來(lái)的屬性復(fù)用了方法優(yōu)點(diǎn)父類的方法得到了復(fù)用。
javascript中實(shí)現(xiàn)繼承的方式有很多種,一般都是通過(guò)原型鏈和構(gòu)造函數(shù)來(lái)實(shí)現(xiàn)。下面對(duì)各種實(shí)現(xiàn)方式進(jìn)行分析,總結(jié)各自的優(yōu)缺點(diǎn)。一 原型繼承
let Super = functioin(name = "eric") { this.name = name; this.getName = function() { return this.name; } } let Sub = function(sex = "male") { this.sex = sex; } Sub.prototype = new Super("eric"); //通過(guò)改變?cè)蛯?duì)象實(shí)現(xiàn)繼承 Sub.prototype.constructor = Sub // 保持構(gòu)造函數(shù)和原型對(duì)象的完整性 let sub1 = new Sub("male") sub2 = new Sub("female"); console.log(sub1.getName()); // eric console.log(sub1.hasOwnProperty("name")) // false 說(shuō)明是繼承而來(lái)的屬性 console.log(sub1.getName === sub2.getName) // true,復(fù)用了方法
優(yōu)點(diǎn):父類的方法(getName)得到了復(fù)用。
缺點(diǎn):同理父類的屬性(name)也是復(fù)用,即子類實(shí)例沒(méi)有自己的屬性。
二 構(gòu)造函數(shù)實(shí)現(xiàn)繼承let Super = function(name = "eric") { this.name = name; this.getName = function() { return this.name; } } let Sub = function(name, sex) { Super.call(this, name); this.sex = sex; } let sub1 = new Sub("eric", "male"); let sub2 = new Sub("ada", "female"); console.log(sub1.name) // "eric" console.log(sub1.hasOwnProperty("name")) // true 說(shuō)明不是繼承而來(lái),是自己的屬性 console.log(sub1.getName === sub2.getName) // false 方法沒(méi)有得到復(fù)用
優(yōu)點(diǎn):子類的每個(gè)實(shí)例都有自己的屬性(name),不會(huì)相互影響。
缺點(diǎn):但是繼承父類方法的時(shí)候就不需要這種特性,沒(méi)有實(shí)現(xiàn)父類方法的復(fù)用。
三 組合式繼承let Super = function(name = "eric") { this.name = name; } Super.prototype = { constructor: Super, getName() { return this.name; } } let Sub = function(sex) { Super.call(this, "eric"); //繼承父類屬性 this.sex = sex; } Sub.prototype = new Super("eric"); //繼承父類方法 Sub.prototype.constructor = Sub; let sub1 = new Sub("male"), sub2 = new Sub("female"); console.log(sub1.name); // "eric" console.log(sub1.hasOwnProperty("name")); // true 自己的屬性 console.log(sub1.getName === sub2.getName); // true 復(fù)用了方法 console.log(Sub.prototype) // { name: "eric" } console.log(sub1) // { name: "eric", sex: "male" }
優(yōu)點(diǎn):繼承了上述兩種方式的優(yōu)點(diǎn),摒棄了缺點(diǎn),復(fù)用了方法,子類又有各自的屬性。
缺點(diǎn):因?yàn)楦割悩?gòu)造函數(shù)被執(zhí)行了兩次,子類的原型對(duì)象(Sub.prototype)中也有一份父類的實(shí)例屬性(name),而且這些屬性會(huì)被子類實(shí)例(sub1,sub2)的屬性覆蓋掉(即通過(guò)sub1.name訪問(wèn)不到Sub.prototype上的name屬性),也存在內(nèi)存浪費(fèi)。
四 寄生組合式繼承let Super = function(name = "eric") { this.name = name; } Super.prototype = { constructor: Super, getName() { return this.name; } } let Sub = function(sex, name) { Super.call(this, name); this.sex = sex; } // 組合繼承的缺點(diǎn)就是在繼承父類方法的時(shí)候調(diào)用了父類構(gòu)造函數(shù),從而造成內(nèi)存浪費(fèi), // 現(xiàn)在只要解決了這個(gè)問(wèn)題就完美了。那在復(fù)用父類方法的時(shí)候, // 使用Object.create方法也可以達(dá)到目的,沒(méi)有調(diào)用父類構(gòu)造函數(shù),問(wèn)題解決。 Sub.prototype = Object.create(Super.prototype); // 當(dāng)然這個(gè)地方也可以使用Object.setPrototypeOf(Sub.prototype, Super.prototype) // 因?yàn)楦囊粋€(gè)對(duì)象的隱士原型(__proto__)對(duì)瀏覽器和js引擎都是很慢對(duì)操作,所以建議使用Object.create()創(chuàng)建一個(gè)具有指定原型對(duì)象的新對(duì)象 Sub.prototype.constructor = Sub;五 es6中的class
class Super() { constructor(props = { name: "eric" }) { this.name = props.name; } setName(name) { this.name = name; } getName() { return this.name; } } class Sub extends Super { constructor(props) { super(props = { sex: "male" }); // 創(chuàng)建實(shí)例,繼承父類屬性和方法 this.sex = props.sex; } } let sub1 = new Sub({ name: "eric", sex: "male" }) let sub2 = new Sub({ name: "eric", sex: "female" }) sub1.setName("ada"); console.log(sub1.getName(),sub2.getName()) // ada,eric,屬性沒(méi)復(fù)用,各自實(shí)例都有自己的屬性。 console.log(sub1.getName === sub2.getName) // true; 復(fù)用了父類的方法 console.log(Sub.prototype.sex) // undefined // 子類原型對(duì)象上沒(méi)有父類構(gòu)造函數(shù)中賦值的屬性,不是組合式繼承
由以上結(jié)果可以看到es6中的class只不過(guò)是一種語(yǔ)法糖,通過(guò)上面的驗(yàn)證得知符合寄生組合繼承的特點(diǎn),但這只是猜測(cè),class具體都做了哪些操作還不是很清楚,后面有時(shí)間,對(duì)class做一下研究。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/83717.html
摘要:深入系列第十五篇,講解各種繼承方式和優(yōu)缺點(diǎn)。優(yōu)點(diǎn)融合原型鏈繼承和構(gòu)造函數(shù)的優(yōu)點(diǎn),是中最常用的繼承模式。寄生組合式繼承為了方便大家閱讀,在這里重復(fù)一下組合繼承的代碼組合繼承最大的缺點(diǎn)是會(huì)調(diào)用兩次父構(gòu)造函數(shù)。 JavaScript深入系列第十五篇,講解JavaScript各種繼承方式和優(yōu)缺點(diǎn)。 寫在前面 本文講解JavaScript各種繼承方式和優(yōu)缺點(diǎn)。 但是注意: 這篇文章更像是筆記,哎...
摘要:前言作為中最重要的內(nèi)容之一,繼承問(wèn)題一直是我們關(guān)注的重點(diǎn)。如果一個(gè)類別繼承自另一個(gè)類別,就把這個(gè)稱為的子類,而把稱為的父類別也可以稱是的超類。 前言 作為 JavaScript 中最重要的內(nèi)容之一,繼承問(wèn)題一直是我們關(guān)注的重點(diǎn)。那么你是否清晰地知道它的原理以及各種實(shí)現(xiàn)方式呢 閱讀這篇文章,你將知道: 什么是繼承 實(shí)現(xiàn)繼承有哪幾種方式 它們各有什么特點(diǎn) 這里默認(rèn)你已經(jīng)清楚的知道構(gòu)造函...
摘要:通常有這兩種繼承方式接口繼承和實(shí)現(xiàn)繼承。理解繼承的工作是通過(guò)調(diào)用函數(shù)實(shí)現(xiàn)的,所以是寄生,將繼承工作寄托給別人做,自己只是做增強(qiáng)工作。適用基于某個(gè)對(duì)象或某些信息來(lái)創(chuàng)建對(duì)象,而不考慮自定義類型和構(gòu)造函數(shù)。 一、繼承的概念 繼承,是面向?qū)ο笳Z(yǔ)言的一個(gè)重要概念。通常有這兩種繼承方式:接口繼承和實(shí)現(xiàn)繼承。接口繼承只繼承方法簽名,而實(shí)現(xiàn)繼承則繼承實(shí)際的方法。 《JS高程》里提到:由于函數(shù)沒(méi)有簽名,...
摘要:深入之繼承的多種方式和優(yōu)缺點(diǎn)深入系列第十五篇,講解各種繼承方式和優(yōu)缺點(diǎn)。對(duì)于解釋型語(yǔ)言例如來(lái)說(shuō),通過(guò)詞法分析語(yǔ)法分析語(yǔ)法樹,就可以開始解釋執(zhí)行了。 JavaScript深入之繼承的多種方式和優(yōu)缺點(diǎn) JavaScript深入系列第十五篇,講解JavaScript各種繼承方式和優(yōu)缺點(diǎn)。 寫在前面 本文講解JavaScript各種繼承方式和優(yōu)缺點(diǎn)。 但是注意: 這篇文章更像是筆記,哎,再讓我...
摘要:基本類型引用類型原型構(gòu)造函數(shù)上有屬性,為原型對(duì)象為實(shí)例對(duì)象,每個(gè)對(duì)象上都有,而指向的是原型對(duì)象,而原型對(duì)象上有屬性,指向的是上一級(jí)的原型對(duì)象。 基本類型 String ,null,undefined,number,boolean 引用類型:object 原型: function People(name,sex){ this.name=name; this.sex=sex...
閱讀 2623·2023-04-26 00:07
閱讀 2432·2021-11-15 11:37
閱讀 639·2021-10-19 11:44
閱讀 2164·2021-09-22 15:56
閱讀 1717·2021-09-10 10:50
閱讀 1497·2021-08-18 10:21
閱讀 2565·2019-08-30 15:53
閱讀 1630·2019-08-30 11:11