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