多數(shù)人在學(xué)習(xí)JavaScript的時(shí)候,都是做Web的時(shí)候旬陡,需要表單驗(yàn)證,或者是一些簡單的DOM操作语婴,如同我上篇所講描孟,處在一個(gè)“輔助”的地位。
處在“輔助”地位的JavaScript砰左,我們總是抱著解決問題就行的態(tài)度匿醒,自然不會(huì)關(guān)注其過多的特性。那么缠导,今天我們就來聊聊在開發(fā)中有哪些特性是我們必須要了解的廉羔!
?
JavaScript的結(jié)構(gòu)
JavaScript分為三個(gè)部分
ECMAScript ?JavaScript本身的語法
DOM ?全稱Document Object Model ,針對HTML Document操作的API僻造,例如document.getElementByID
BOM ?全稱Browser Object Model憋他,針對瀏覽器Window操作的API,例如window.location
在一般的項(xiàng)目中孩饼,多數(shù)人會(huì)關(guān)注DOM操作,所以忽略了JavaScript語法本身的精髓竹挡。我們今天重點(diǎn)關(guān)注的就是:JavaScript本身語法镀娶。
請注意:我們在前端使用JavaScript時(shí),多數(shù)是以操作DOM為目的此迅,學(xué)習(xí)JavaScript語言的精髓汽畴,本身就是為了讓我們更優(yōu)雅的“操作DOM”!
由于JS的每一個(gè)特性都包含太多內(nèi)容耸序,所以我們只能分多篇來講忍些,今日我們先講繼承!我對于繼承的講解方法會(huì)和百度的帖子迥異坎怪,但更通俗一些罢坝,希望大家看過之后可以秒懂“繼承”。
面向?qū)ο蟮娜笤瓌t:封裝搅窿,繼承嘁酿,多態(tài)。我們不能脫離其他法則單講繼承男应,封裝是繼承的先決條件闹司,多態(tài)是繼承要達(dá)到的目的,三者是糾合在一起的沐飘!
1. 封裝
封裝是對象的表現(xiàn)形式游桩。比如Java中,封裝的表現(xiàn)形式是JavaBean耐朴,在JavaScript就是Object刷后,通俗點(diǎn)就是{}
我們來看JavaScript的一個(gè)簡單對象
對象的兩個(gè)要點(diǎn):屬性和行為宪摧, name作為屬性,work作為行為,已經(jīng)滿足封裝的基本要素缓呛,所以我們認(rèn)定student是一個(gè)對象扮授。它的對象就是如此簡單闸天。
我們這里多插一個(gè)知識點(diǎn):對象和我們平時(shí)講的JSON犬绒,有什么不同呢?
JSON是JavaScript對象標(biāo)記語言俯艰,JSON的作用是數(shù)據(jù)傳輸捡遍,“數(shù)據(jù)”具有不可變性,所以JSON只能包含屬性竹握,不能有行為画株。即:JSON中沒有任何JavaScript方法!它們的區(qū)別就在于有沒有包含方法。
要記住JSON和對象的區(qū)別谓传,只要我們記住一句繞口令即可:JSON一定是JavaScript對象蜈项,JavaScript對象不一定是JSON!
2. 繼承
所有的JavaScript的對象续挟,在其生成的時(shí)候紧卒,編譯器都會(huì)附加給對象一個(gè)特殊的屬性:prototype,即大家常說的原型诗祸。理解原型是理解JavaScript繼承的重點(diǎn)跑芳。
原型有一個(gè)最最最重要的特點(diǎn): 強(qiáng)單例 。同一類型的對象擁有的原型是一個(gè)直颅,比如Array博个,所有的Array實(shí)例的原型只有一個(gè)!
下面的代碼中功偿,arr1和arr2的prototype指向的是同一個(gè)盆佣,如果設(shè)置arr1的為null,arr2的也就為null了械荷。
我們在看JavaScript的API時(shí)共耍,經(jīng)常看到Array的方法有:push shift slice splice等等吨瞎,這些方法都是存在Array的prototype中痹兜。
我們再來看看,當(dāng)我們調(diào)用一個(gè)JavaScript對象方法的時(shí)候颤诀,它的解析器是如何工作的佃蚜?
例如調(diào)用arr1.push 方法,
1. 解析器會(huì)首先遍歷“對象本身”的方法着绊,如果找到,則直接調(diào)用熟尉,否則归露,繼續(xù)第二步驟
2. 解析器會(huì)查看對象的Prototype對象中是否存在該方法,存在則調(diào)用斤儿,不存在就拋出Exception
講到這里剧包,大家應(yīng)該秒懂“Prototype”是個(gè)什么東西了吧! 其實(shí)就是給對象附加一個(gè)內(nèi)部對象而已往果,這個(gè)內(nèi)部對象又是一個(gè)單例的疆液。作為單例,相對于對象本身肯定高效率的陕贮! 但是也是危險(xiǎn)的6橛汀!
比如剛才我賤賤的設(shè)置arr1的prototype為null,那完蛋了5羧薄卜录!整個(gè)頁面的Array都要出錯(cuò)!如果我這樣修改眶明,估計(jì)有些不明所以的程序員都要哭了艰毒,尼瑪瀏覽器會(huì)罵人!
看過以上搜囱,請大家記壮笄啤:每個(gè)JavaScript對象都分為兩個(gè)部分:“本身”和prototype。那么對象的繼承也是針對這兩個(gè)部分展開的蜀肘。繼承的目的是為了擴(kuò)展绊汹,說更通俗點(diǎn)就是,為了給某個(gè)對象附加更多的方法幌缝。
這時(shí)候問題就回歸為,如何給JavaScrit對象附加方法灸促?
針對本身附加
上面的student,這時(shí)候又來了小明同學(xué)涵卵,但是小明同學(xué)比Aric多了一項(xiàng)技能浴栽,會(huì)擼呀擼! 要如何實(shí)現(xiàn)呢轿偎?
jquery的extend的原理就是把一個(gè)對象的所有屬性和方法附加到另外一個(gè)上面典鸡!
針對prototype附加
如果上面代碼修改為:小明.prototype.lol = func...這樣也實(shí)現(xiàn)了同樣的功能,但是這時(shí)候Aric也有了LOL這個(gè)功能坏晦!
百度上多數(shù)講繼承的帖子萝玷,都會(huì)有如下這樣的偽代碼, 我們看過以上文章昆婿,是不是就明白了為什么球碉! 我曾經(jīng)看過無數(shù)的繼承的帖子,一直也不懂prototype是個(gè)什么玩意2智睁冬!
關(guān)于繼承的使用,這里基本落幕看疙,大家心中都應(yīng)該有一個(gè)初步的印象了豆拨。當(dāng)你懂的事物的原理后,再學(xué)習(xí)起來應(yīng)該就更加得心應(yīng)手了能庆。
3. 多態(tài)
面向?qū)ο蟮娜笤瓌t之一:多態(tài)施禾。多態(tài)分為對象多態(tài)和方法多態(tài)! 這是兩個(gè)不同的概念搁胆。
對象多態(tài)
就是我們時(shí)趁指悖看到的貓狗都屬于動(dòng)物邮绿,貓叫是喵喵,狗卻是汪汪拓巧,這是多態(tài)的最直接體現(xiàn)斯碌。至于更多實(shí)現(xiàn)細(xì)節(jié),請大家自行百度肛度。
方法多態(tài)
方法多態(tài)傻唾,就是方法名字相同,但是傳入的參數(shù)列表不同承耿!這個(gè)在Java或者C#中都被我們玩爛了冠骄! 在JavaScript中由于沒有參數(shù)列表,一般都用方法的內(nèi)部函數(shù)Arguments來表述加袋!Arguments是偽Array凛辣,里面放的就是當(dāng)前方法的參數(shù)列表!
具體使用過程中职烧,即可通過Arguments中元素的個(gè)數(shù)來實(shí)現(xiàn)方法多態(tài)扁誓。
很多人都說JavaScript不是面向?qū)ο蟮木幊陶Z言,其實(shí)是對JavaScript的誤解蚀之!面向?qū)ο蟮娜笤瓌t蝗敢,JavaScript都能實(shí)現(xiàn)!只是實(shí)現(xiàn)的方式有些不同足删,卻有異曲同工之妙寿谴。
說在最后的話:
JavaScript的繼承不像Java那樣有明確的語法規(guī)則,它是靈活多變的失受。所以寫慣Java這種類型的人員讶泰,非常討厭其語法,我在剛?cè)腴T時(shí)拂到,也是如此痪署。但是在當(dāng)你掌握了它,它的靈活多變會(huì)變成編程中的利器兄旬,劍之所指惠桃,所向披靡!
希望每一位有心學(xué)習(xí)JavaScript的程序員辖试,都能理解其繼承原理!
接下來劈狐,我們會(huì)繼續(xù)講解JavaScript的其他特性罐孝!在講解這些特性的同時(shí),我會(huì)結(jié)合其一些知名類庫肥缔,比如jQuery莲兢,講解這些特性在其中的應(yīng)用。