摘要:面向?qū)ο笕筇匦跃褪欠庋b繼承和多態(tài),簡單理解,對于貓這種動物,它本身就是一個封裝好的類,你只需要供它吃喝輸入,它就能表現(xiàn)貓的行為輸出,同時它繼承了動物所具有的習(xí)性吃東西等,而不同的貓因為所處環(huán)境或者習(xí)性的不同,可能會有不同的表現(xiàn)和行為,這就
面向?qū)ο笕筇匦跃褪欠庋b繼承和多態(tài),簡單理解,對于貓這種動物,它本身就是一個封裝好的類,你只需要供它吃喝(輸入),它就能表現(xiàn)貓的行為(輸出),同時它繼承了動物所具有的習(xí)性(吃東西等~),而不同的貓因為所處環(huán)境或者習(xí)性的不同,可能會有不同的表現(xiàn)和行為,這就是多態(tài)。
封裝
把客觀事物封裝成抽象的類,隱藏屬性和方法的實現(xiàn)細(xì)節(jié),僅對外公開接口。
① 在ES6之前,沒有class這個概念,借由原型對象和構(gòu)造函數(shù)來實現(xiàn)
function Cat(name, food) { this.name = name // 公有屬性 this.food = food } Cat.prototype.say = function() { // 公有方法 console.log(this.name + " likes eating " + this.food) } Cat.see = function() { console.log("這是靜態(tài)方法,無需實例化可調(diào)用") } var cat = new Cat("Lazier","mouse") cat.say() // 實例共享原型屬性和方法
② ES6的class
class Cat{ constructor(name, food){ this.name = name this.food = food } static see() { console.log("這是靜態(tài)方法,無需實例化可調(diào)用") } say(){ console.log(this.name+" likes eating " + this.food) } } var cat = new Cat("Lazier","mouse") cat.say()
以上class的基本實現(xiàn)原理如下 ↓
var Cat = function(){ function Cat(name, food){ this.name = name this.food = food } // 執(zhí)行掛載函數(shù),創(chuàng)建類 createClass(Cat,[{key:"say",value:function(){ console.log(this.name+" likes eating " + this.food) }}],[{key:"see",value:function(){ console.log("這是靜態(tài)方法,無需實例化可調(diào)用")}]) } // 定義對象屬性 let defineProperties = function(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i] Object.defineProperty(target, descriptor.key, descriptor) } } // 掛載函數(shù),將靜態(tài)或動態(tài)方法分別掛載到Cat和Cat的prototype上 var createClass = function({ return function(Constructor,protoProps,staticProps){ if(protoProps){ // 原型方法 defineProperties(Constructor.prototype,protoProps) } if(staticProps){ // 靜態(tài)方法 defineProperties(Constructor,staticProps) } } })
了解面向?qū)ο蟮墓小⑺接?、靜態(tài)屬性和方法可以看下面這篇文章的總結(jié)
js面向?qū)ο笾?、私有、靜態(tài)屬性和方法詳解
繼承
子類可以使用父類的所有功能,并且對這些功能進(jìn)行擴(kuò)展。繼承的過程,就是從一般到特殊的過程。
js實現(xiàn)繼承有多種方式
原型鏈繼承
// 將子類的prototype指向父類的實例 function Parent(){} function Son(){} Son.prototype = new Parent() // * 把Son的原型對象的constructor指向Son,解決類型判斷問題 Son.prototype.constructor = Son 借助構(gòu)造函數(shù)繼承(使用call和apply實現(xiàn)繼承) function Parent(){} function Son(){ // 將父類函數(shù)中的this,強行綁定為子類的this // 可傳參 Parent.call(this, arguments); } 組合繼承 // 原型屬性方法由原型鏈實現(xiàn)繼承,實例屬性方法由借用構(gòu)造函數(shù)實現(xiàn)繼承 // 這樣,在原型上定義方法實現(xiàn)了函數(shù)復(fù)用,又保證每個實例都有它自己的屬性 function Parent(name){ this.name = name } function Son(name, age){ // 繼承父類的實例屬性方法,之后再添加自己的實例屬性方法 Parent.call(this, name); this.age = age } Son.prototype = new Parent() // 重寫Son的原型對象 Son.prototype.constructor = Son var demo = new Son("jacksonzhou", 23) 寄生式組合繼承 – 現(xiàn)在最常用的繼承方法 // 獲得父類原型屬性方法的副本,解決組合繼承的屬性重復(fù)問題 function inheritPrototype(son, parent) { var prototype = object(parent.prototype) prototype.constructor = son son.prototype = prototype } function Parent(name){ this.name = name } function Son(name, age){ Parent.call(this, name) this.age = age } Son.prototype = inheritPrototype(Son, Parent) var demo = new Son("jacksonzhou", 23)
多態(tài)
同一操作用在不同對象上,可以產(chǎn)生不同的解釋和不同的執(zhí)行結(jié)果
var makeSound=function(animal){ animal.sound() } // 聲明狗的構(gòu)造函數(shù) var Dog=function(){} Dog.prototype.sound=function(){ console.log("汪汪汪") } // 聲明貓的構(gòu)造函數(shù) var Cat=function(){} Cat.prototype.sound=function(){ console.log("喵喵喵") } // 分別調(diào)用他們的叫法 makeSound(new Dog()) makeSound(new Cat()) // 非多態(tài)寫法 var makeSound=function(animal){ if(animal instanceof Dog){ console.log("汪汪汪") }else if(animal instanceof Cat){ console.log("喵喵喵") } } var Dog=function(){} var Cat=function(){} // 分別調(diào)用他們的叫法 makeSound(new Dog()) makeSound(new Cat()) // 很明顯,后續(xù)有其他動物加入都要去修改makeSound函數(shù),很不優(yōu)雅! 這里要介紹下方法重載 方法重載是讓類以統(tǒng)一的方式處理不同類型數(shù)據(jù)的一種手段。表現(xiàn)為多個同名函數(shù)同時存在,但具有不同的參數(shù)個數(shù)或類型。調(diào)用方法時通過傳遞給它們的不同參數(shù)個數(shù)和參數(shù)類型來決定具體使用哪個方法, 這也是一種多態(tài)性。 其實js本身并沒有這個概念,但我們可以通過操作參數(shù)的類數(shù)組arguments,根據(jù)該類數(shù)組的長度以及其元素的類型來選擇不同的實現(xiàn),來模擬實現(xiàn)函數(shù)重載效果 // js的函數(shù)參數(shù)相當(dāng)靈活~可理解成一個動態(tài)的類數(shù)組 // 不加參數(shù),調(diào)用時有傳入?yún)?shù)也不會報錯 function countCat(){ if(arguments.length==1){ console.log(`這是一只貓,${arguments[0]}`) } else if(arguments.length==2){ console.log(`這是兩只貓,${arguments[0]}和${arguments[1]}`) } else{ console.log("沒貓了~") } } countCat() countCat("Tom") countCat("Tom","Mary")
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/106883.html
摘要:我們都知道面向?qū)ο髶碛腥筇卣?,分別為封裝繼承多態(tài),其實在腳本語言中是不存在多態(tài)的,但是可以用的方式實現(xiàn)多態(tài)中的兩種效果重載重寫,那下面我們就來說一下面向?qū)ο蟮奶卣鞣庋b把抽象出的屬性和對屬性的方法封裝在一起對外實現(xiàn)接口開放,說白了就是封裝一 我們都知道js面向?qū)ο髶碛腥筇卣?,分別為封裝、繼承、多態(tài),其實在javaScript腳本語言中是不存在多態(tài)的,但是可以用js的方式實現(xiàn)多態(tài)中的兩...
摘要:會造成內(nèi)存浪費的問題構(gòu)造函數(shù)繼承聲明父類聲明子類生成實例組合式繼承組合式繼承是汲取了兩者的優(yōu)點,既避免了內(nèi)存浪費,又使得每個實例化的子類互不影響。 寫在前面 既然是淺談,就不會從原理上深度分析,只是幫助我們更好地理解... 面向?qū)ο笈c面向過程 面向?qū)ο蠛兔嫦蜻^程是兩種不同的編程思想,剛開始接觸編程的時候,我們大都是從面向過程起步的,畢竟像我一樣,大家接觸的第一門計算機(jī)語言大概率都是C語...
摘要:為什么要學(xué)習(xí)設(shè)計模式做事情之前問個為什么總是好的。設(shè)計模式的使用方法關(guān)于使用方式,像我這種初學(xué)者最容易犯的錯誤就是生搬硬套,但是模仿本來也是學(xué)習(xí)的一個過程,最重要的事情是在模仿中要學(xué)會思考。 為什么要學(xué)習(xí)設(shè)計模式? 做事情之前問個為什么總是好的。關(guān)于設(shè)計模式的好壞,我在知乎上也看過一些討論,有知友對其提出過一些疑問,里面有一些關(guān)于設(shè)計模式的觀點: 設(shè)計模式有何不妥,所謂的荼毒體現(xiàn)在哪...
摘要:很多情況下,通常一個人類,即創(chuàng)建了一個具體的對象。對象就是數(shù)據(jù),對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍(lán)圖或原型。在中,對象通過對類的實體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
摘要:很多情況下,通常一個人類,即創(chuàng)建了一個具體的對象。對象就是數(shù)據(jù),對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍(lán)圖或原型。在中,對象通過對類的實體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
閱讀 3547·2021-11-22 11:59
閱讀 950·2021-09-27 13:36
閱讀 3612·2021-09-24 09:47
閱讀 2260·2021-09-01 11:39
閱讀 979·2021-08-31 09:37
閱讀 2311·2021-08-05 10:01
閱讀 1673·2019-08-30 15:55
閱讀 701·2019-08-30 15:54