摘要:這個(gè)構(gòu)造函數(shù)的不管從調(diào)用方式還是內(nèi)部寫法就都很有的感覺,但是從用途上來(lái)說(shuō),它其實(shí)更靠近的概念是中的工廠方法。到這里,所有關(guān)于繼承的東西講完了,接下來(lái)準(zhǔn)備準(zhǔn)備說(shuō)說(shuō)當(dāng)中的封裝
所謂的對(duì)象,就是抽象化的數(shù)據(jù)本身一個(gè)面向?qū)ο筠D(zhuǎn)向面向原型的困惑
我發(fā)現(xiàn)Javascript這門語(yǔ)言每次翻開都會(huì)帶給人新感受,尤其是看完其他語(yǔ)言的面向?qū)ο笤賮?lái)看它,但是如果你也是過(guò)來(lái)人就一定記得教科書里面冗長(zhǎng)乏味的面向?qū)ο?,所有的書上都?huì)跟你這么說(shuō):面向?qū)ο笫菍?duì)要解決的問(wèn)題的一種抽象,比如很經(jīng)典的Java或者C++,class就是根基,然后類實(shí)例化出對(duì)象balabala....初學(xué)者來(lái)看的話其實(shí)是很難接受的,但是挺過(guò)這個(gè)時(shí)期,就會(huì)產(chǎn)生一種理所應(yīng)當(dāng)?shù)母杏X,就會(huì)覺得:面向?qū)ο螽?dāng)然需要類啦當(dāng)然需要實(shí)例化啦,不然怎么繼承的之類的。當(dāng)然基本上主流的面向?qū)ο笳Z(yǔ)言都會(huì)提供基本相同的概念。但是有個(gè)異類就是JavaScript,如果你用其他語(yǔ)言的概念來(lái)理解這個(gè)世界里的對(duì)象可能會(huì)找不著北。因?yàn)檫@個(gè)世界里沒(méi)有“類”這個(gè)東西,所有的東西都是對(duì)象。
朝下看的時(shí)候,我建議學(xué)過(guò)面向?qū)ο蟮娜送簟邦悺边@個(gè)東西,不然很容易就會(huì)搞混。
那到底什么是對(duì)象呢?這個(gè)問(wèn)題問(wèn)淺了是個(gè)傻問(wèn)題問(wèn)深了又變成了一個(gè)哲學(xué)問(wèn)題,每個(gè)語(yǔ)言甚至每個(gè)人都有不同的答案,但是如果你只有十天來(lái)設(shè)計(jì)一門語(yǔ)言的話,你肯定也是想把這個(gè)東西設(shè)計(jì)的越簡(jiǎn)單越好,所以對(duì)JavaScript來(lái)說(shuō),對(duì)象就是屬性+方法,簡(jiǎn)單來(lái)說(shuō)就是這樣:
var Person={ name :"XXX", age:18, address:"YYY", gender:0, eat:function(){ console.log("食"); }, wear:function(){ console.log("衣"); }, live:function(){ console.log("住"); }, walk:function(){ console.log("行"); } } Person.eat();
這樣一個(gè)對(duì)象就寫好了,不僅如此,我們?cè)谶\(yùn)行時(shí)還可以動(dòng)態(tài)的修改內(nèi)部對(duì)象的屬性,以及增加方法等等非常自由。第一眼看上去非常的直觀,但是仔細(xì)想想看,問(wèn)題其實(shí)很多,比如,屬性這樣無(wú)限制的訪問(wèn)一點(diǎn)安全性都沒(méi)有,再比如我想再要生成一個(gè)人但是名字叫小紅的,就很費(fèi)勁,再再比如我怎么實(shí)現(xiàn)繼承?問(wèn)題很多我們一個(gè)一個(gè)來(lái)說(shuō)
純對(duì)象怎么完成繼承?其實(shí)繼承說(shuō)白了,要做的事情就是把兩個(gè)毫不相干的人建立父子關(guān)系,但是怎么建立呢?Javascript語(yǔ)言的對(duì)象生來(lái)都有一個(gè)特殊屬性叫__proto__,我們可以用這個(gè)屬性來(lái)關(guān)聯(lián)其他對(duì)象,就像這樣:
var Teacher={ //這里添加老師的屬性和方法 __proto__:Person } Teacher.eat();
這樣,兩個(gè)對(duì)象之間就建立了聯(lián)系,人類(對(duì)象)是老師(對(duì)象)的原型,用圖表示就是:
這樣一條鏈條把對(duì)象之間聯(lián)系起來(lái),這樣使用Teacher調(diào)用eat方法的時(shí)候找不到就順著鏈子朝上找一直找到頭如果沒(méi)有就報(bào)錯(cuò),看起來(lái)很完美。
怎么欺騙其他世界的程序員?但是大家都知道高級(jí)語(yǔ)言都是要吸引別人來(lái)用的,這個(gè)方式實(shí)在是和其他語(yǔ)言不太一樣,怎么吸引其他人來(lái)用呢?本著不行就封裝一層的原則于是語(yǔ)言提供了構(gòu)造函數(shù),但是這個(gè)構(gòu)造函數(shù)到這里為止還是和其他語(yǔ)言有完全不同的意義(當(dāng)然使用上區(qū)別不大)。
function Person(){ this.name=name; this.eat=function(){ console.log(this.name+" eat food now"); } } ming =new Student("xiaoming"); hong =new Student("xiaohong");
這個(gè)構(gòu)造函數(shù)的不管從調(diào)用方式還是內(nèi)部寫法就都很有Java Class的感覺,但是從用途上來(lái)說(shuō),它其實(shí)更靠近的概念是Java中的工廠方法。而且使用的時(shí)候還使用了new這個(gè)關(guān)鍵字,同時(shí)解決了上面的那個(gè)不用生成一個(gè)對(duì)象就寫一大串代碼的尷尬。同時(shí)還很靈活,你還是可以在ming或者h(yuǎn)ong這個(gè)對(duì)象上動(dòng)態(tài)添加方法。
但是上面的操作有個(gè)很操蛋的問(wèn)題就是,因?yàn)檫@個(gè)語(yǔ)言沒(méi)有類只有對(duì)象,所以你構(gòu)造函數(shù)里寫的方法會(huì)原封不動(dòng)的出現(xiàn)在新生成的對(duì)象當(dāng)中,這意味著每個(gè)新生成的對(duì)象都有相同的函數(shù),這就很浪費(fèi)而且對(duì)象多了還吃內(nèi)存。設(shè)計(jì)者當(dāng)然也想到了這個(gè)問(wèn)題,他用純對(duì)象的思考方式想了一個(gè)解決辦法,舉個(gè)例子:
現(xiàn)在有一個(gè)Person構(gòu)造函數(shù)(上面那樣的),通常使用它來(lái)生成新的對(duì)象(小紅小明等等)來(lái)通過(guò)原型鏈來(lái)訪問(wèn)父對(duì)象的方法,基于這個(gè)模型那我索性就再生成一個(gè)對(duì)象掛在Person下面,用一個(gè)屬性指向它(大家都知道我說(shuō)的就是prototype這個(gè)屬性啦),公共的方法完全可以都放在這個(gè)對(duì)象里面,但是怎么調(diào)用這些方法呢?其實(shí)大家既然都是對(duì)象,小明小紅的__proto__里面寫的只要是Person.prototype就完事了呀,說(shuō)了這么多用一個(gè)圖來(lái)標(biāo)識(shí)一下:
對(duì)我們來(lái)說(shuō)只需要關(guān)注橫著一排的原型鏈就行了,至于Person構(gòu)造函數(shù)是一個(gè)函數(shù)自然也是一個(gè)對(duì)象(函數(shù)也是對(duì)象),同樣自然有自己的原型鏈但是這里和主體無(wú)關(guān)就不體現(xiàn)在圖上了。
如果原型鏈的知識(shí)都差不多了的話我覺得就可以放出下面這張廣為人知的圖來(lái)記憶一番了:
然后寫了這么多,你就發(fā)現(xiàn)其實(shí)繼承在Javascript當(dāng)中原來(lái)也是一個(gè)謊言--只要把新的對(duì)象掛上原型鏈就算是“繼承”了。那問(wèn)題就變成了怎么構(gòu)建原型鏈,我們還是放上道爺發(fā)明的一種方式來(lái)實(shí)現(xiàn)繼承(方法多種多樣,我覺得道爺?shù)倪@種橋接并且不污染上下文環(huán)境的方式相當(dāng)好用)
//父類 function Student(props){ this.name=props.name||"unnamed"; } Student.prototype.hello=function(){ console.log("Hello, " + this.name + "!"); } //子類 function PrimaryStudent(props) { Student.call(this, props); this.grade = props.grade || 1; } //使用一個(gè)空構(gòu)造函數(shù)來(lái)橋接 function F(){} F.prototype=Student.prototype; //把原本指向Function.prototype的指針指向父類 PrimaryStudent.prototype=new F();//橋接子類對(duì)象到一個(gè)F的匿名對(duì)象上 PrimaryStudent.prototype.constructor=PrimaryStudent;//糾正構(gòu)造函數(shù)指向 PrimaryStudent.prototype.getGrade=function(){ return this.grade; } // 開始測(cè)試 var xiaoming=new PrimaryStudent({ name:"xiaoming", grade:2 }); console.log(xiaoming.__proto__===PrimaryStudent.prototype); console.log(xiaoming.__proto__.__proto__===Student.prototype); console.log(xiaoming instanceof PrimaryStudent); console.log(xiaoming instanceof Student);
使用一張圖展示上面的代碼做了什么:
done!關(guān)系就是這么橋接好的,我們?nèi)绻僭谕饷姘粚雍瘮?shù)就完全可以做工具函數(shù)來(lái)用
ES6標(biāo)準(zhǔn)下的語(yǔ)法糖很明顯,上面的這個(gè)做法很費(fèi)勁,或者說(shuō),不直觀沒(méi)法吸引別人來(lái)用,所以ES6標(biāo)準(zhǔn)里加了一個(gè)很Java的語(yǔ)法糖,就像下面這么寫:
class Person { constructor(name){ this.name=name; } hello(){ console.log(`${this.name} say hello to you!`); } } class Teacher extends Person{ constructor(name,gender){ super(name); this.gender=gender; } myGender(){ console.log(`${this.name}"s gender is ${this.gender}`); } } var x=new Teacher("niuguangzhe","nan"); x.myGender();
可以說(shuō)是Java味道十足,但是別忘了,其實(shí)語(yǔ)言的內(nèi)部仍然是原型鏈。
到這里,所有關(guān)于繼承的東西講完了,接下來(lái)準(zhǔn)備準(zhǔn)備說(shuō)說(shuō)Javascript當(dāng)中的封裝
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/89975.html
摘要:個(gè)人前端文章整理從最開始萌生寫文章的想法,到著手開始寫,再到現(xiàn)在已經(jīng)一年的時(shí)間了,由于工作比較忙,更新緩慢,后面還是會(huì)繼更新,現(xiàn)將已經(jīng)寫好的文章整理一個(gè)目錄,方便更多的小伙伴去學(xué)習(xí)。 showImg(https://segmentfault.com/img/remote/1460000017490740?w=1920&h=1080); 個(gè)人前端文章整理 從最開始萌生寫文章的想法,到著手...
摘要:上下文切換上下文最直觀的表現(xiàn)就是代碼塊中的,通常在面向?qū)ο蟮木幊讨杏玫?,?lái)指代當(dāng)前類生成的對(duì)應(yīng)實(shí)例,與其他語(yǔ)言的一致。咦,是干嘛的,有沒(méi)有其他方式實(shí)現(xiàn),請(qǐng)自行谷歌。 分享第一篇,關(guān)于 NodeJS —— Javascript 的常用知識(shí)以及如何從 Javascript 開發(fā)者過(guò)渡到 NodeJS 開發(fā)者(不會(huì)介紹具體的框架)。在讀本文前,希望你對(duì) javascript 有一些初步的認(rèn)識(shí)...
摘要:入門,第一個(gè)這是一門很新的語(yǔ)言,年前后正式公布,算起來(lái)是比較年輕的編程語(yǔ)言了,更重要的是它是面向程序員的函數(shù)式編程語(yǔ)言,它的代碼運(yùn)行在之上。它通過(guò)編輯類工具,帶來(lái)了先進(jìn)的編輯體驗(yàn),增強(qiáng)了語(yǔ)言服務(wù)。 showImg(https://segmentfault.com/img/bV1xdq?w=900&h=385); 新的一年不知不覺已經(jīng)到來(lái)了,總結(jié)過(guò)去的 2017,相信小伙們一定有很多收獲...
摘要:入門,第一個(gè)這是一門很新的語(yǔ)言,年前后正式公布,算起來(lái)是比較年輕的編程語(yǔ)言了,更重要的是它是面向程序員的函數(shù)式編程語(yǔ)言,它的代碼運(yùn)行在之上。它通過(guò)編輯類工具,帶來(lái)了先進(jìn)的編輯體驗(yàn),增強(qiáng)了語(yǔ)言服務(wù)。 showImg(https://segmentfault.com/img/bV1xdq?w=900&h=385); 新的一年不知不覺已經(jīng)到來(lái)了,總結(jié)過(guò)去的 2017,相信小伙們一定有很多收獲...
閱讀 1011·2023-04-25 19:35
閱讀 2675·2021-11-22 09:34
閱讀 3707·2021-10-09 09:44
閱讀 1732·2021-09-22 15:25
閱讀 2947·2019-08-29 14:00
閱讀 3382·2019-08-29 11:01
閱讀 2609·2019-08-26 13:26
閱讀 1744·2019-08-23 18:08