多數(shù)人在學(xué)習(xí)JavaScript的時候,都是做Web的時候,需要表單驗證,或者是一些簡單的DOM操作,如同我上篇所講,處在一個“輔助”的地位。
處在“輔助”地位的JavaScript,我們總是抱著解決問題就行的態(tài)度,自然不會關(guān)注其過多的特性。那么,今天我們就來聊聊在開發(fā)中有哪些特性是我們必須要了解的!
?
JavaScript的結(jié)構(gòu)
JavaScript分為三個部分
ECMAScript ?JavaScript本身的語法
DOM ?全稱Document Object Model ,針對HTML Document操作的API,例如document.getElementByID
BOM ?全稱Browser Object Model,針對瀏覽器Window操作的API,例如window.location
在一般的項目中,多數(shù)人會關(guān)注DOM操作,所以忽略了JavaScript語法本身的精髓。我們今天重點關(guān)注的就是:JavaScript本身語法。
請注意:我們在前端使用JavaScript時,多數(shù)是以操作DOM為目的,學(xué)習(xí)JavaScript語言的精髓,本身就是為了讓我們更優(yōu)雅的“操作DOM”!
由于JS的每一個特性都包含太多內(nèi)容,所以我們只能分多篇來講,今日我們先講繼承!我對于繼承的講解方法會和百度的帖子迥異,但更通俗一些,希望大家看過之后可以秒懂“繼承”。
面向?qū)ο蟮娜笤瓌t:封裝,繼承,多態(tài)。我們不能脫離其他法則單講繼承,封裝是繼承的先決條件,多態(tài)是繼承要達到的目的,三者是糾合在一起的!
1. 封裝
封裝是對象的表現(xiàn)形式。比如Java中,封裝的表現(xiàn)形式是JavaBean,在JavaScript就是Object,通俗點就是{}
我們來看JavaScript的一個簡單對象

對象的兩個要點:屬性和行為, name作為屬性,work作為行為,已經(jīng)滿足封裝的基本要素,所以我們認定student是一個對象。它的對象就是如此簡單。
我們這里多插一個知識點:對象和我們平時講的JSON,有什么不同呢?
JSON是JavaScript對象標記語言,JSON的作用是數(shù)據(jù)傳輸,“數(shù)據(jù)”具有不可變性,所以JSON只能包含屬性,不能有行為。即:JSON中沒有任何JavaScript方法!它們的區(qū)別就在于有沒有包含方法。

要記住JSON和對象的區(qū)別,只要我們記住一句繞口令即可:JSON一定是JavaScript對象,JavaScript對象不一定是JSON!
2. 繼承
所有的JavaScript的對象,在其生成的時候,編譯器都會附加給對象一個特殊的屬性:prototype,即大家常說的原型。理解原型是理解JavaScript繼承的重點。
原型有一個最最最重要的特點: 強單例 。同一類型的對象擁有的原型是一個,比如Array,所有的Array實例的原型只有一個!
下面的代碼中,arr1和arr2的prototype指向的是同一個,如果設(shè)置arr1的為null,arr2的也就為null了。

我們在看JavaScript的API時,經(jīng)常看到Array的方法有:push shift slice splice等等,這些方法都是存在Array的prototype中。
我們再來看看,當我們調(diào)用一個JavaScript對象方法的時候,它的解析器是如何工作的?
例如調(diào)用arr1.push 方法,
1. 解析器會首先遍歷“對象本身”的方法,如果找到,則直接調(diào)用,否則,繼續(xù)第二步驟
2. 解析器會查看對象的Prototype對象中是否存在該方法,存在則調(diào)用,不存在就拋出Exception
講到這里,大家應(yīng)該秒懂“Prototype”是個什么東西了吧! 其實就是給對象附加一個內(nèi)部對象而已,這個內(nèi)部對象又是一個單例的。作為單例,相對于對象本身肯定高效率的! 但是也是危險的??!
比如剛才我賤賤的設(shè)置arr1的prototype為null,那完蛋了??!整個頁面的Array都要出錯!如果我這樣修改,估計有些不明所以的程序員都要哭了,尼瑪瀏覽器會罵人!

看過以上,請大家記?。好總€JavaScript對象都分為兩個部分:“本身”和prototype。那么對象的繼承也是針對這兩個部分展開的。繼承的目的是為了擴展,說更通俗點就是,為了給某個對象附加更多的方法。
這時候問題就回歸為,如何給JavaScrit對象附加方法?
針對本身附加
上面的student,這時候又來了小明同學(xué),但是小明同學(xué)比Aric多了一項技能,會擼呀擼! 要如何實現(xiàn)呢?

jquery的extend的原理就是把一個對象的所有屬性和方法附加到另外一個上面!
針對prototype附加
如果上面代碼修改為:小明.prototype.lol = func...這樣也實現(xiàn)了同樣的功能,但是這時候Aric也有了LOL這個功能!
百度上多數(shù)講繼承的帖子,都會有如下這樣的偽代碼, 我們看過以上文章,是不是就明白了為什么! 我曾經(jīng)看過無數(shù)的繼承的帖子,一直也不懂prototype是個什么玩意!!
關(guān)于繼承的使用,這里基本落幕,大家心中都應(yīng)該有一個初步的印象了。當你懂的事物的原理后,再學(xué)習(xí)起來應(yīng)該就更加得心應(yīng)手了。
3. 多態(tài)
面向?qū)ο蟮娜笤瓌t之一:多態(tài)。多態(tài)分為對象多態(tài)和方法多態(tài)! 這是兩個不同的概念。
對象多態(tài)
就是我們時??吹降呢埞范紝儆趧游铮埥惺沁鬟?,狗卻是汪汪,這是多態(tài)的最直接體現(xiàn)。至于更多實現(xiàn)細節(jié),請大家自行百度。
方法多態(tài)
方法多態(tài),就是方法名字相同,但是傳入的參數(shù)列表不同!這個在Java或者C#中都被我們玩爛了! 在JavaScript中由于沒有參數(shù)列表,一般都用方法的內(nèi)部函數(shù)Arguments來表述!Arguments是偽Array,里面放的就是當前方法的參數(shù)列表!
具體使用過程中,即可通過Arguments中元素的個數(shù)來實現(xiàn)方法多態(tài)。
很多人都說JavaScript不是面向?qū)ο蟮木幊陶Z言,其實是對JavaScript的誤解!面向?qū)ο蟮娜笤瓌t,JavaScript都能實現(xiàn)!只是實現(xiàn)的方式有些不同,卻有異曲同工之妙。

說在最后的話:
JavaScript的繼承不像Java那樣有明確的語法規(guī)則,它是靈活多變的。所以寫慣Java這種類型的人員,非常討厭其語法,我在剛?cè)腴T時,也是如此。但是在當你掌握了它,它的靈活多變會變成編程中的利器,劍之所指,所向披靡!
希望每一位有心學(xué)習(xí)JavaScript的程序員,都能理解其繼承原理!
接下來,我們會繼續(xù)講解JavaScript的其他特性!在講解這些特性的同時,我會結(jié)合其一些知名類庫,比如jQuery,講解這些特性在其中的應(yīng)用。