日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

JavaScript 常見的繼承方式匯總

瀏覽:143日期:2023-10-12 17:15:40

原型鏈機(jī)制:

在ECMAscript中描述了原型鏈的概念,并將原型鏈作為實(shí)現(xiàn)繼承的主要方法,其基本思想就是利用原型讓一個(gè)引用類型繼承另一個(gè)引用類型的屬性和方法。

構(gòu)造函數(shù)和原型還有實(shí)例之間的關(guān)系:

每個(gè)構(gòu)造函數(shù)都有一個(gè)原型對(duì)象(prototype),原型對(duì)象都包含一個(gè)指向構(gòu)造函數(shù)的指針(constructor),而實(shí)例都包含一個(gè)指向原型對(duì)象的內(nèi)部指針 ( __propto__ ) 。關(guān)系圖如下圖所示:

JavaScript 常見的繼承方式匯總

每一個(gè)Function都是Object基類的一個(gè)實(shí)例,所以每一個(gè)Function上都有一個(gè)__proto__指向了Object.prototype。

當(dāng)查找一個(gè)實(shí)例的屬性時(shí),會(huì)先從這個(gè)實(shí)例的自定義屬性上找,如果沒有的話通過__proto__去實(shí)例所屬類的原型上去找,如果還沒有的話再通過原型(原型也是對(duì)象,只要是對(duì)象就有__proto__屬性)的__proto__到Object的原型上去找,一級(jí)一級(jí)的找,如果沒有就undefined。

所以引用類型之間的繼承就是通過原型鏈機(jī)制實(shí)現(xiàn)的。

一.原型繼承

原型繼承:把父類的私有+公有的屬性和方法,都作為子類公有的屬性。

核心:不是把父類私有+公有的屬性克隆一份一模一樣的給子類的公有。他是通過__proto__建立和子類之間的原型鏈,當(dāng)子類的實(shí)例需要使用父類的屬性和方法的時(shí)候,可以通過__proto__一級(jí)級(jí)找上去使用。 

function Parent(){ this.x = 199; this.y = 299;}Parent.prototype.say = function(){ console.log(’say’)}function Child(){ this.g = 90;}Child.prototype = new Parent();var p = new Parent();var c = new Child();console.dir(c)

實(shí)現(xiàn)的本質(zhì)是重寫了原型對(duì)象 ,通過將子類的原型指向了父類的實(shí)例,所以子類的實(shí)例就可以通過__proto__訪問到 Child.prototype 也就是 Parent的實(shí)例,這樣就可以訪問到父類的私有方法。然后再通過__proto__指向父類的prototype就可以獲得到父類原型上的方法。

這樣就做到了將父類的私有、公有方法和屬性都當(dāng)做子類的公有屬性。這樣就通過原型鏈實(shí)現(xiàn)了繼承。

但是別忘了默認(rèn)的原型,因?yàn)樗幸妙愋投际抢^承了Object的,所有說子類也可以訪問到Object上的方法如toString() 、valueOf() 等。

結(jié)果如下圖所示:

JavaScript 常見的繼承方式匯總

有的時(shí)候我們需要在子類中添加新的方法或者是重寫父類的方法時(shí)候,切記一定要放到替換原型的語句之后。

function Parent(){ this.x = 199; this.y = 299;}Parent.prototype.say = function(){ console.log(’say’)}function Child(){ this.g = 90;}/*Child.prototype.Bs = function(){ console.log(’Bs’)}*/在這里寫子類的原型方法和屬性是沒用的因?yàn)闀?huì)改變?cè)偷闹赶颍詰?yīng)該放到重新指定之后Child.prototype = new Parent();Child.prototype.constructor=Child//由于重新修改了Child的原型導(dǎo)致默認(rèn)原型上的constructor丟失,我們需要自己添加上,其實(shí)沒啥用,加不加都一樣Child.prototype.Bs = function(){ console.log(’Bs’)}Child.prototype.say = function(){ console.log(’之后改的’)}var p = new Parent();var c = new Child();console.dir(c)c.Bs() //Bsc.say() // 之后改的p.say() //say 不影響父類實(shí)例訪問父類的方法

存在的問題:

1. 子類繼承父類的屬性和方法是將父類的私有屬性和公有方法都作為自己的公有屬性和方法,我們要清楚一件事情就是我們操作基本數(shù)據(jù)類型的時(shí)候操作的是值,在操作應(yīng)用數(shù)據(jù)類型的時(shí)候操作的是地址,如果說父類的私有屬性中引用類型的屬性,那他被子類繼承的時(shí)候會(huì)作為公有屬性,這樣子類一操作這個(gè)屬性的時(shí)候,會(huì)影響到子類二。

2. 在創(chuàng)建子類的實(shí)例時(shí),不能向父類型的構(gòu)造函數(shù)中傳遞參數(shù)。應(yīng)該說是沒有辦法在不影響所有對(duì)象實(shí)例的情況下,給父類的構(gòu)造函數(shù)傳遞參數(shù)。

所以在實(shí)際中很少單獨(dú)使用原型繼承。

二.call繼承

改變方法的this指向,同時(shí)執(zhí)行方法。 在子類構(gòu)造函數(shù)中父類.call(this) 可以將父類的私有變成子類的私有。

function Parent() { this.x = 100; this.y = 199;}Parent.prototype.fn = function() {} function Child() { this.d = 100; Parent.call(this); //構(gòu)造函數(shù)中的this就是當(dāng)前實(shí)例}var p = new Parent();var c = new Child();console.log(p) //Parent {x: 100, y: 199}console.log(c) //Child {d: 100, x: 100, y: 199}

在子類的構(gòu)造函數(shù)中,改變父類的this指向,改變?yōu)樽宇惖膶?shí)例,同時(shí)運(yùn)行父類方法,這樣父類中的this.x就變成了子類的實(shí)例.x ,通過這種方法就可以繼承了父類的私有屬性,且只能繼承父類的私有屬性和方法。

三.冒充對(duì)象繼承

冒充對(duì)象繼承的原理是循環(huán)遍歷父類實(shí)例,然后父類實(shí)例的私有方法全部拿過來添加給子類實(shí)例。

function Parent(){ this.x = 100;}Parent.prototype.getX = function(){ console.log(’getX’)}function Child(){ var p = new Parent(); for(var attr in p){//for in 可以遍歷到原型上的公有自定義屬性 this[attr] = p[attr] } //以下代碼是只獲得到私有方法和屬性,如果不加這個(gè)的話就可以遍歷到所有方法和屬性 /*if(e.hasOwnProperty(attr)){ this[attr] = e[attr] } e.propertyIsEnumerable()*///可枚舉屬性==> 可以拿出來一一列舉的屬性}var p = new Parent();var c = new Child();console.dir(c)

for in 可以遍歷到原型上的公有自定義屬性 ,所以他可以拿到私有和公有的屬性和方法,這個(gè)你可以遍歷私有和公有的,需要你加限制條件。但是如果不做hasOwnProperty判斷那么就是把父類的公有的和私有的都拿過來當(dāng)私有的。

四.混合繼承

就是將call繼承和原型繼承集合在一起,無論是私有的還是公有的都拿過來了。但是有個(gè)問題就是子類的原型上的多了一套父類私有屬性,但是不會(huì)產(chǎn)生問題。因?yàn)樽宇惖乃接袑傩砸灿幸惶紫嗤耐ㄟ^call繼承拿過來的。

function Parent(){ this.x=100;}Parent.prototype.getX = function(){}function Child(){ Parent.call(this);}Child.prototype = new Parent();Child.prototype.constructor = Child;var p = new Parent();var c = new Child();console.log(c)//Child {x: 100}

存在的問題:

無論在什么情況下,都會(huì)調(diào)用兩次構(gòu)造函數(shù):一次是在創(chuàng)建子類型原型的時(shí)候,另一次是在子類型構(gòu)造函數(shù)的內(nèi)部,沒錯(cuò),子類型最終會(huì)包含父類型對(duì)象的全部實(shí)例屬性,但我們不得不在調(diào)用子類構(gòu)造函數(shù)時(shí)重寫這些屬性。

還有一種就是call+拷貝繼承

//混合繼承:call繼承+拷貝繼承 function extend(newEle,oldEle){ for(var attr in oldEle){ newEle[attr]=oldEle[attr]; } } function F(){ this.x=100; this.showX=function(){} } F.prototype.getX=function(){}; F.prototype.getX1=function(){}; var f1=new F; console.dir(f1) function S(){ F.call(this)//call繼承 } extend(S.prototype, F.prototype);//拷貝繼承 S.prototype.cc=function(){ } var p1=new S; console.dir(p1);

這種方式使用call繼承將父類的私有方法繼承過來,使用for in 拷貝將父類的公有屬性和方法繼承過來,比較實(shí)用。

五.中間件繼承

中間件繼承就是通過原型鏈的機(jī)制,子類的prototype.__proto__本來應(yīng)該是直接指向Object.prototype。

從父類的原型上的__proto__也可以到Object.prototype,在父類.prototype上停留了下,父類.prototype就是一個(gè)中間件,所以子類可以繼承到父類的公有方法當(dāng)做自己的公有方法。

function Parent(){ this.x = 100;}Parent.prototype.getX = function(){}function Child(){ }Child.prototype.__proto__ = Parent.prototype;var p = new Parent();var c = new Child()console.log(c)

六.寄生組合式繼承

   寄生式組合: call繼承+Object.create();

所謂寄生組合式繼承就是通過借用構(gòu)造函數(shù)來繼承屬性,通過原型鏈的混合形式來繼承方法。

基本思路是不必為了指定子類的原型而調(diào)用父類的構(gòu)造函數(shù),我們所需要的就是父類型原型的一個(gè)副本。

本質(zhì)上,就是使用寄生式繼承父類的原型,然后再將結(jié)果指定給子類的原型。

function F(){ this.x=100;}F.prototype.showX=function(){};function S(){ this.y = 200 F.call(this)//只繼承了私有的;}function inheritPrototype(subType,superType){ var prototype = Object.create(superType.prototype);//創(chuàng)建對(duì)象 prototype.constructor = subType;//增強(qiáng)對(duì)象 subType.prototype = prototype;//指定對(duì)象}inheritPrototype(S,F)var p1=new S;console.dir(p1)

1、第一步是創(chuàng)建父類型原型的一個(gè)副本。

2、第二步是為創(chuàng)建的副本增加constructor屬性,從而彌補(bǔ)了因?yàn)橹貙懺投サ哪J(rèn)的constructor屬性。

3、第三步是將創(chuàng)建的對(duì)象賦值給子類型的原型。

這個(gè)例子的高效率體現(xiàn)在他只調(diào)用了一次SuperType 構(gòu)造函數(shù),并且因此避免了在SubType.prototype上面創(chuàng)建不必要的、多余的屬性。與此同時(shí)原型鏈還能保持不變,所以可以正常使用instanceof 和 isPrototypeOf() ,所以寄生組合繼承是引用類型最理想的繼承方法。

七.class繼承

class 可以通過extends關(guān)鍵字實(shí)現(xiàn)繼承,這比 ES5 的通過修改原型鏈實(shí)現(xiàn)繼承,要清晰和方便很多。

class Father{ constructor(x, y) { this.x = x; this.y = y; } toString() { return ’(’ + this.x + ’, ’ + this.y + ’)’; }}class Son extends Father{ constructor(x,y,color){ super(x,y); // 調(diào)用父類的constructor(x, y) this.color = color; } toString() {console.log( super.toString()+this.color); // 調(diào)用父類的toString() }}let son = new Son(3,4,’red’);son.toString();//結(jié)果為(3,4)red

上面代碼定義了一個(gè)Son類,該類通過extends關(guān)鍵字,繼承了Father類的所有屬性和方法。

上面代碼中,constructor方法和toString方法之中,都出現(xiàn)了super關(guān)鍵字,它在這里表示父類的構(gòu)造函數(shù),用來新建父類的this對(duì)象。

子類必須在constructor方法中調(diào)用super方法,否則新建實(shí)例時(shí)會(huì)報(bào)錯(cuò)。這是因?yàn)樽宇愖约旱膖his對(duì)象,必須先通過父類的構(gòu)造函數(shù)完成塑造,得到與父類同樣的實(shí)例屬性和方法,然后再對(duì)其進(jìn)行加工,加上子類自己的實(shí)例屬性和方法。如果不調(diào)用super方法,子類就得不到this對(duì)象。

以上就是JavaScript 常見的繼承方式匯總的詳細(xì)內(nèi)容,更多關(guān)于JavaScript 繼承方式的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: JavaScript
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国产精品嫩草99av在线| 亚洲欧洲一区二区天堂久久| 视频一区国产视频| 在线亚洲精品| 蜜桃视频一区二区| 日本不卡中文字幕| 久久不卡日韩美女| sm久久捆绑调教精品一区| 特黄特色欧美大片| 蜜桃视频在线观看一区| 日韩va亚洲va欧美va久久| 国产日韩三级| 最新国产精品| 蜜桃精品视频| 天堂资源在线亚洲| 日韩精品一级中文字幕精品视频免费观看 | 日韩精品成人| 欧美国产极品| 国产激情久久| 999精品在线| 蜜臀精品久久久久久蜜臀| 日韩avvvv在线播放| 国产精品不卡| 欧美在线影院| 国产精品成人国产| 狠狠久久婷婷| 美日韩一区二区三区| 亚洲精品97| 97久久亚洲| 成人小电影网站| 一区二区三区网站| 大香伊人久久精品一区二区 | 日韩在线黄色| 色爱综合网欧美| 99国产精品| 久久亚洲黄色| 亚洲视频国产精品| 女生影院久久| 欧美亚洲三区| 亚洲欧洲日本mm| 精品中文字幕一区二区三区四区| 午夜久久黄色| 国产成人精品福利| 日本成人精品| 亚洲黄色在线| 国产+成+人+亚洲欧洲在线| 神马午夜久久| 欧美国产三级| 亚洲在线观看| 日韩黄色大片网站| 国产精品中文字幕亚洲欧美| 午夜在线精品偷拍| 日本免费一区二区三区四区| 久久国内精品| 久久成人精品| 亚洲成人国产| 国产成人精品一区二区免费看京| 只有精品亚洲| 欧美一区二区三区激情视频| 久久av免费看| 日韩黄色在线观看| 日韩精品2区| 蜜桃久久久久| 欧美久久一区二区三区| 丝袜脚交一区二区| 久久美女精品| 日韩成人综合| 欧美国产精品| 久久精品99国产精品| 噜噜噜久久亚洲精品国产品小说| 97精品国产| 久久av电影| 国产精品亚洲产品| 欧美在线日韩| 日韩成人午夜精品| 天堂久久av| 亚洲精品va| 蜜桃视频欧美| 欧美日韩国产探花| 国产一区清纯| 亚洲国产专区校园欧美| 日韩免费av| 日韩欧美不卡| 成人福利av| 国产乱码午夜在线视频| 国产精品99一区二区三| 韩国一区二区三区视频| 精品中文在线| 国产精品毛片久久| 成人亚洲精品| 成人片免费看| 国产中文欧美日韩在线| 国产精品激情| 精品三级在线观看视频| 精品久久久久久久| 中文一区一区三区高中清不卡免费| 久久久久久色| 日韩高清一级| 国产图片一区| 国产精品久一| 精品久久精品| 日韩欧美午夜| 久久精品国产亚洲夜色av网站| 亚洲二区视频| 视频一区视频二区在线观看| 亚洲最新av| 亚洲精品免费观看| 国产欧美三级| 9999国产精品| 好吊日精品视频| 日韩专区视频网站| 欧美国产免费| 久久婷婷丁香| 视频一区二区三区在线| 欧美专区一区| 日韩av有码| 制服诱惑一区二区| 久久国产视频网| 岛国av在线网站| 国产色综合网| 国产精品中文字幕制服诱惑| 精品少妇一区| 欧美成人午夜| 综合激情网站| 国产精品66| 久久中文亚洲字幕| 亚洲日韩中文字幕一区| 美女视频网站久久| 婷婷成人综合| 日韩高清在线一区| 国产精品不卡| 巨乳诱惑日韩免费av| 久久爱www.| 狠狠干成人综合网| 国产精品对白| 影院欧美亚洲| 日韩在线观看中文字幕| 久久精品国产精品亚洲毛片| 午夜av一区| 国产精品nxnn| 激情91久久| 国产精品sss在线观看av| 91精品国产成人观看| 日韩精品免费一区二区夜夜嗨| 国产成人免费| 亚洲不卡视频| 亚洲精品一区三区三区在线观看| 亚洲区第一页| 亚洲成a人片| 91麻豆精品激情在线观看最新| 久久人人精品| 日本不卡一二三区黄网| 日本免费一区二区三区四区| 日韩国产成人精品| 欧美福利一区| 激情中国色综合| 四虎精品一区二区免费| 亚洲人成在线网站| 国产精选久久| 亚洲免费在线| 成人片免费看| 国产精品亚洲二区| 国产精品美女久久久浪潮软件| 国产一区二区三区日韩精品| 日本精品另类| 99热精品在线观看| sm捆绑调教国产免费网站在线观看 | 亚洲欧美视频| 日韩欧美网址| 欧美激情福利| 亚洲网址在线观看| 欧美成人国产| 日韩欧美字幕| 福利在线一区| 久久亚洲黄色| 国产精品一级在线观看| 亚洲三级网站| 99国产成+人+综合+亚洲欧美| 久久99影视| 日韩国产成人精品| 噜噜噜久久亚洲精品国产品小说| 九九色在线视频| 国产一区二区三区视频在线| 久久精品超碰| 911精品国产| 日韩中文av| 亚洲一区二区三区久久久| 欧美影院三区| 99久久亚洲精品蜜臀| 欧美国产美女| 国产一区二区三区亚洲综合| 国产精品成人自拍| 91精品丝袜国产高跟在线| 亚洲欧洲一区| 一区在线观看| 欧美日韩国产欧| 亚洲免费精品| 视频一区视频二区在线观看| 免费久久精品视频| 亚洲男女自偷自拍|