摘要:使用原型鏈實現(xiàn)對原型屬性和方法的繼承,用借用構(gòu)造函數(shù)模式實現(xiàn)對實例屬性的繼承。
我們之前介紹了javascript面向?qū)ο蟮姆庋b的相關內(nèi)容,還介紹了js的call方法,今天開始討論js的繼承
這篇文章參考了《javascript高級程序設計》(第三版),但內(nèi)容不局限于,網(wǎng)上很多關于js繼承的相關內(nèi)容都是來自于這本書,有興趣的同學可以翻閱查看
我們先通過一個栗子,了解一下原型鏈繼承。留意代碼注釋內(nèi)容
//創(chuàng)建自定義構(gòu)造函數(shù) function Hqg() { this.name = "洪七公"; } //在當前構(gòu)造函數(shù)的原型鏈上添加屬性skill Hqg.prototype.skill = "打狗棒" //通過自定義構(gòu)造函數(shù)Hqg實例化一個對象gj const gj = new Hqg() console.log(gj.skill);//=>打狗棒 //通過自定義構(gòu)造函數(shù)Hqg實例化一個對象hr const hr = new Hqg() console.log(hr.skill);//=>打狗棒
一個簡單的栗子,郭靖和黃蓉都從洪七公那里繼承到了skill 打狗棒,貌似沒什么問題,我們繼續(xù)看demo
//上面代碼省略 const gj = new Hqg()//通過自定義構(gòu)造函數(shù)Hqg實例化一個對象gj gj.skill = "降龍十八掌"http://重新對gj的skill賦值 console.log(gj.skill);//=>降龍十八掌 //通過自定義構(gòu)造函數(shù)Hqg實例化一個對象hr const hr = new Hqg() console.log(hr.skill);//=>打狗棒
對郭靖的skill重新賦值,也沒有影響黃蓉的skill,我們打印一下gj
gj的skill屏蔽掉了原型鏈上的skill,所以gj的skill是降龍十八掌,而hr的skill依然是打狗棒
function Hqg() { this.name = "洪七公"; } Hqg.prototype.skill = ["打狗棒"] const gj = new Hqg() gj.skill.push ("降龍十八掌")//找到了原型鏈中的skill,并對其執(zhí)行push操作,從而改變了構(gòu)造函數(shù)中的skill屬性 console.log(gj.skill); //=>["打狗棒", "降龍十八掌"] const hr = new Hqg() //構(gòu)造函數(shù)中的skill已經(jīng)被改變 console.log(hr.skill); //=>["打狗棒", "降龍十八掌"]
總結(jié)一下,gj和hr都是Hqg的實例,繼承Hqg的屬性和方法,當Hqg的屬性或者方被改變了,后面的實例也會受影響,有時候這并不是我們希望的結(jié)果
借用構(gòu)造函數(shù)借用?就是使用call或者apply改變一下this指向,
就是子類的構(gòu)造函數(shù)內(nèi)部通過call或者apply調(diào)用父類的構(gòu)造函數(shù),如果對call方法有不了解的地方,可以翻看昨天的文章
舉一個栗子
//創(chuàng)建一個構(gòu)造函數(shù),并添加一些屬性 function Hqg() { this.name = "洪七公"; this.job = "幫主"; this.skill = ["降龍十八掌", "打狗棒"] } //創(chuàng)建一個構(gòu)造函數(shù),并借用了Hqg的構(gòu)造函數(shù) function Hr() { Hqg.call(this) this.name = "黃蓉"; this.job = ["相夫", "教子"] } //創(chuàng)建一個構(gòu)造函數(shù),并借用了Hqg的構(gòu)造函數(shù) function Gj() { Hqg.call(this) this.name = "郭靖"; this.job = ["吃飯", "睡覺"] } const hr = new Hr(); console.log(hr); const gj = new Gj(); console.log(gj);
輸出
這樣就避免了原型鏈繼承中,構(gòu)造函數(shù)中的屬性或者方法被其他實例所改變的問題
??:這里要注意call方法的執(zhí)行順序:
//部分代碼省略 function Hr() { this.name = "黃蓉"; this.job = ["相夫", "教子"] Hqg.call(this) } function Gj() { this.name = "郭靖"; this.job = ["吃飯", "睡覺"] Hqg.call(this) } //部分代碼省略
如果call在之后執(zhí)行就會導致一個問題
值會被覆蓋,這個要注意!
這個算是一個升級的玩法吧
function Hqg(name,job,skill) { this.name = name; this.job = job; this.skill = skill } function Hr() { Hqg.call(this,"黃蓉",["相夫", "教子"],["打狗棒"]) } function Gj() { Hqg.call(this,"郭靖",["吃飯", "睡覺"],["降龍十八掌"]) } const hr = new Hr(); console.log(hr); const gj = new Gj(); console.log(gj);
輸出
將原型鏈和借用構(gòu)造函數(shù)技術組合到一起。
使用原型鏈實現(xiàn)對原型屬性和方法的繼承,用借用構(gòu)造函數(shù)模式實現(xiàn)對實例屬性的繼承。
這樣既通過在原型上定義方法實現(xiàn)了函數(shù)復用,又能保證每個實例都有自己的屬性
一個栗子
function Hqg(name) { this.name = name this.skill = ["降龍十八掌","打狗棒"] } Hqg.prototype.sayName = function () { console.log(this.name); } function Hero(name, job) { Hqg.call(this, name); this.job = job } Hero.prototype = new Hqg(); Hero.prototype.constructor = Hero; Hero.prototype.sayJob = function () { console.log(this.job) } var gj = new Hero("郭靖", "吃飯睡覺"); gj.skill.push("九陰真經(jīng)"); console.log(gj); var hr = new Hero("黃蓉", "相夫教子"); console.log(hr);
先看下輸出
我們把這個組合繼承和之前的兩個原型鏈繼承和借用構(gòu)造函數(shù)繼承進行比較
不難發(fā)現(xiàn)組合繼承融合了他們的優(yōu)點,成為javascript中最常用的繼承模式
今天就討論前三個,還有三個明天繼續(xù),不見不散
參考鏈接
你們真的了解JS的繼承嘛?
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/100165.html
摘要:之前,本質(zhì)上不能算是一門面向?qū)ο蟮木幊陶Z言,因為它對于封裝繼承多態(tài)這些面向?qū)ο笳Z言的特點并沒有在語言層面上提供原生的支持。所以在中出現(xiàn)了等關鍵字,解決了面向?qū)ο笾谐霈F(xiàn)了問題。 ES6之前,javascript本質(zhì)上不能算是一門面向?qū)ο蟮木幊陶Z言,因為它對于封裝、繼承、多態(tài)這些面向?qū)ο笳Z言的特點并沒有在語言層面上提供原生的支持。但是,它引入了原型(prototype)的概念,可以讓我們以...
摘要:那你們肯定會問為什么共用,而沒有共用呢,下面就給你解釋,請看引用類型是共用的值類型是私用的。 引言 面向?qū)ο蟮木幊陶Z言都具繼承這一機制,而 JavaScript 是基于原型(Prototype)面向?qū)ο蟪绦蛟O計,所以它的實現(xiàn)方式也是基于原型(Prototype)實現(xiàn)的. 繼承的方式 類式繼承 構(gòu)造函數(shù)繼承 組合繼承 原型式繼承 寄生式繼承 寄生組合式繼承 1.類式繼承 //聲明父...
摘要:很多情況下,通常一個人類,即創(chuàng)建了一個具體的對象。對象就是數(shù)據(jù),對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍圖或原型。在中,對象通過對類的實體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
摘要:很多情況下,通常一個人類,即創(chuàng)建了一個具體的對象。對象就是數(shù)據(jù),對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍圖或原型。在中,對象通過對類的實體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
摘要:很多情況下,通常一個人類,即創(chuàng)建了一個具體的對象。對象就是數(shù)據(jù),對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍圖或原型。在中,對象通過對類的實體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
摘要:實現(xiàn)思路使用原型鏈實現(xiàn)對原型方法和方法的繼承,而通過借用構(gòu)造函數(shù)來實現(xiàn)對實例屬性的繼承。繼承屬性繼承方法以上代碼,構(gòu)造函數(shù)定義了兩個屬性和。 JS面向?qū)ο蟮某绦蛟O計之繼承的實現(xiàn)-組合繼承 前言:最近在細讀Javascript高級程序設計,對于我而言,中文版,書中很多地方翻譯的差強人意,所以用自己所理解的,嘗試解讀下。如有紕漏或錯誤,會非常感謝您的指出。文中絕大部分內(nèi)容引用自《Java...
閱讀 3406·2021-11-24 09:39
閱讀 1797·2021-11-17 09:33
閱讀 3503·2021-10-12 10:12
閱讀 5019·2021-09-22 15:51
閱讀 1112·2019-08-30 13:11
閱讀 3572·2019-08-30 10:59
閱讀 564·2019-08-30 10:48
閱讀 1311·2019-08-26 13:48