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