摘要:的屬性是指向的,繼承的屬性在寄生式繼承創(chuàng)建一個(gè)僅用于封裝繼承過(guò)程的函數(shù),該函數(shù)在內(nèi)部以某種形式來(lái)做增強(qiáng)對(duì)象,最后返回對(duì)象。缺點(diǎn)跟構(gòu)造函數(shù)模式一樣,每次創(chuàng)建對(duì)象都會(huì)創(chuàng)建一遍方法。
前言
上文講到j(luò)s中的原型鏈,這篇文章對(duì)每種繼承方式具體分析一下
原型鏈繼承原型鏈繼承就是將父類(lèi)的實(shí)例賦給子類(lèi)的原型對(duì)象,話(huà)不多說(shuō),看下代碼
function parent(name){ this.name = "111"; } parent.prototype.getName = function(){ console.log(this.name) } function child(){} child.prototype = new parent(); const child1 = new child() child1.getName();//111 console.log(child.name);//111
優(yōu)點(diǎn): 可以直接繼承父類(lèi)的屬性和方法,這里的屬性繼承是通過(guò)__proto__找到的,不是實(shí)例本身?yè)碛械?br>缺點(diǎn): 1.不能向父類(lèi)傳參 2.引用屬性會(huì)被所有實(shí)例共享
function parent(){ this.name = ["111","2222"] } parent.prototype.getName = function(){ console.log(this.name) } function child(){} child.prototype = new parent(); const child1 = new child(); const child2 = new child(); child1.name.push("aaa") console.log(child1.name,child2.name)//["111","2222","aaa"]
3.child的constructor指向parent,應(yīng)該予以修復(fù)
child.prototype.constructor = child;構(gòu)造函數(shù)繼承
構(gòu)造函數(shù)繼承就是在子類(lèi)調(diào)用父類(lèi),看代碼
function parent(name){ this.name = name; } function child(name){ parent.call(this,name); } const child1 = new child("child"); console.log(child1.name)//child
優(yōu)點(diǎn):可以繼承父類(lèi)的屬性(這里的屬性繼承是實(shí)例本身自己的),可以向父類(lèi)傳參,引用類(lèi)型不會(huì)被所有實(shí)例共享,constructor還是指向自己child
缺點(diǎn):不能繼承父類(lèi)原型上的方法,方法都在構(gòu)造函數(shù)中定義,每次創(chuàng)建實(shí)例都會(huì)創(chuàng)建一遍方法。
function parent(name){ this.name = name; this.arr = ["111"] } function child(name){ parent.call(this,name); } const child1 = new child("child1"); const child2 = new child("child2") child1.arr.push("222"); console.log(child1.arr,child2.arr)//(2)?["111", "222"] ["111"]組合繼承
如果結(jié)合原型繼承和構(gòu)造函數(shù)繼承,這樣就可以結(jié)合其優(yōu)點(diǎn),摒棄其缺點(diǎn)了,這就是組合繼承
function parent(name){ this.name = name; this.arr = ["111"] } parent.prototype.getName = function(){ console.log(this.name) } function child(name){ parent.call(this,name) } child.prototype = new parent(); const child1 = new child("child1"); const child2 = new child("child2"); child1.arr.push("222"); child1.getName();//child1 console.log(child1.arr,child2.arr)//2)?["111", "222"] ["111"]
優(yōu)點(diǎn): 可以向父類(lèi)傳參,可以繼承父類(lèi)的屬性(子類(lèi)會(huì)有從父類(lèi)繼承的屬性,__proto__上基本屬性是undefined,引用屬性是有的,看下圖)和原型上的方法,引用屬性不會(huì)被共享
缺點(diǎn): 一個(gè)實(shí)例會(huì)實(shí)例化父類(lèi)兩次,parent.call(this,name)調(diào)用一次,child.prototype = new parent()調(diào)用一次,constructor指向了parent
原型繼承function create(o){ function F(){}; F.prototype = o; return new F(); }
原型繼承其實(shí)就是es5的object.create()的實(shí)現(xiàn)
看下這段代碼
const person = { name: "name", arr: ["111","222"] } const p1 = create(person); const p2 = create(person); p1.name = "p1"; p1.arr.push("aaa"); console.log(p1.name,p2.name);//p1,name console.log(p1.arr,p2.arr);//(3)?["111", "222", "aaa"] (3)?["111", "222", "aaa"]
缺點(diǎn):會(huì)共享引用屬性
注意:修改p1.name的值,p2.name的值并未發(fā)生改變,并不是因?yàn)閜1和p2有獨(dú)立的 name 值,而是因?yàn)閜1.name = "p1",給person1添加了 name 值,并非修改了原型上的 name 值。p1,p2的constructor屬性是指向object的,繼承的屬性在__proto__
創(chuàng)建一個(gè)僅用于封裝繼承過(guò)程的函數(shù),該函數(shù)在內(nèi)部以某種形式來(lái)做增強(qiáng)對(duì)象,最后返回對(duì)象。
function createObj (o) { var clone = object.create(o); clone.sayName = function () { console.log("hi"); } return clone; }
缺點(diǎn):跟構(gòu)造函數(shù)模式一樣,每次創(chuàng)建對(duì)象都會(huì)創(chuàng)建一遍方法。
寄生組合式繼承終極繼承??!寄生組合式繼承,結(jié)合了以上的優(yōu)點(diǎn),來(lái)看下代碼
組合繼承的缺點(diǎn)就是會(huì)調(diào)用兩次父類(lèi),如何避免調(diào)用兩次呢?能不能直接讓子類(lèi)的prototype訪(fǎng)問(wèn)到父類(lèi)的prototype?當(dāng)然可以??!看下面的代碼
function parent(name){ this.name = name; this.arr = ["111"] } parent.prototype.getName = function(){ console.log(this.name) } function child(name){ parent.call(this,name) } //注意!!關(guān)鍵!! function F(){} F.prototype = parent.prototype; child.prototype = new F(); const c1 = new child("c1"); const c2 = new child("c2"); c1.arr.push("ccc"); c1.name = "name"; c1.getName();//name c2.getName();//c2 console.log(c1,c2);//child?{name: "name", arr: Array(2)} child?{name: "c2", arr: Array(1)}
優(yōu)點(diǎn):可以繼承父類(lèi)的屬性和原型上的方法,實(shí)例間不會(huì)共享引用屬性,基本屬性也可以繼承變成自己的屬性,不會(huì)執(zhí)行兩遍父類(lèi)
缺點(diǎn): 子類(lèi)的constructor指向指向了父類(lèi),應(yīng)該修復(fù)之,可以改寫(xiě)如下
可以改寫(xiě)寫(xiě)上面的關(guān)鍵步驟
function create(o){ function F(){} F.prototype = o; return new F(); } function prototype(child,parent){ const p = create(parent.prototype); p.constructor = child; child.prototype = p; }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/108306.html
摘要:深入之繼承的多種方式和優(yōu)缺點(diǎn)深入系列第十五篇,講解各種繼承方式和優(yōu)缺點(diǎn)。對(duì)于解釋型語(yǔ)言例如來(lái)說(shuō),通過(guò)詞法分析語(yǔ)法分析語(yǔ)法樹(shù),就可以開(kāi)始解釋執(zhí)行了。 JavaScript深入之繼承的多種方式和優(yōu)缺點(diǎn) JavaScript深入系列第十五篇,講解JavaScript各種繼承方式和優(yōu)缺點(diǎn)。 寫(xiě)在前面 本文講解JavaScript各種繼承方式和優(yōu)缺點(diǎn)。 但是注意: 這篇文章更像是筆記,哎,再讓我...
摘要:?jiǎn)栴}修改實(shí)例的,即修改了構(gòu)造函數(shù)的原型對(duì)象的共享屬性到此處,涉及到的內(nèi)容大家可以再回頭捋一遍,理解了就會(huì)覺(jué)得醍醐灌頂。 開(kāi)場(chǎng)白 大三下學(xué)期結(jié)束時(shí)候,一個(gè)人跑到帝都來(lái)參加各廠(chǎng)的面試,免不了的面試過(guò)程中經(jīng)常被問(wèn)到的問(wèn)題就是JS中如何實(shí)現(xiàn)繼承,當(dāng)時(shí)的自己也是背熟了實(shí)現(xiàn)繼承的各種方法,回過(guò)頭來(lái)想想?yún)s不知道__proto__是什么,prototype是什么,以及各種繼承方法的優(yōu)點(diǎn)和缺點(diǎn),想必有好...
摘要:中實(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)父類(lèi)的方法得到了復(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 Sup...
摘要:最常見(jiàn)的判斷方法它的官方解釋操作符返回一個(gè)字符串,表示未經(jīng)計(jì)算的操作數(shù)的類(lèi)型。另外,是判斷對(duì)象是否屬于某一類(lèi)型,而不是獲取的對(duì)象的類(lèi)型。多個(gè)窗口意味著多個(gè)全局環(huán)境,不同的全局環(huán)境擁有不同的全局對(duì)象,從而擁有不同的內(nèi)置類(lèi)型構(gòu)造函數(shù)。 js中的數(shù)據(jù)類(lèi)型 js中只有六種原始數(shù)據(jù)類(lèi)型和一個(gè)Object: Boolean Null Undefined Number String Symbol ...
摘要:通常有這兩種繼承方式接口繼承和實(shí)現(xiàn)繼承。理解繼承的工作是通過(guò)調(diào)用函數(shù)實(shí)現(xiàn)的,所以是寄生,將繼承工作寄托給別人做,自己只是做增強(qiáng)工作。適用基于某個(gè)對(duì)象或某些信息來(lái)創(chuàng)建對(duì)象,而不考慮自定義類(lèi)型和構(gòu)造函數(shù)。 一、繼承的概念 繼承,是面向?qū)ο笳Z(yǔ)言的一個(gè)重要概念。通常有這兩種繼承方式:接口繼承和實(shí)現(xiàn)繼承。接口繼承只繼承方法簽名,而實(shí)現(xiàn)繼承則繼承實(shí)際的方法。 《JS高程》里提到:由于函數(shù)沒(méi)有簽名,...
閱讀 925·2021-11-25 09:43
閱讀 1301·2021-11-17 09:33
閱讀 3026·2019-08-30 15:44
閱讀 3316·2019-08-29 17:16
閱讀 485·2019-08-28 18:20
閱讀 1645·2019-08-26 13:54
閱讀 558·2019-08-26 12:14
閱讀 2180·2019-08-26 12:14