javascript
前端判断session对象是否为空_谈谈JavaScript这个语言与前端是否需要面向对象?...
事實(shí)上,一個(gè)語言是否流行與它是否優(yōu)秀沒有任何關(guān)系。JS綁架了整個(gè)Web前端,而我們又沒有其他的選擇。 ——題記
最近這兩年用JavaScript用的比較頻繁。一是2017年時(shí)開始制作小程序課程;二是2018年開啟了Lin-UI和Lin-CMS,無論哪個(gè)開源項(xiàng)目,都嚴(yán)重依賴JS;再加上5.6日上線的NodeJS&KOA新課程,JS就像個(gè)502固體膠,越黏越緊。
本篇文字,一方面講述面向?qū)ο髮?duì)JS編程的重要性,另一方面也必須吐槽一下沒有ES新特性加持的JS真的有點(diǎn)“垃圾”。你可以將沒有ES新特性支持的JS理解成ES5。
我知道很多同學(xué)是JS語言的粉絲,也一定聽說過Atwood的名言:凡是能用JS實(shí)現(xiàn)的最終都將用JS實(shí)現(xiàn)。
但我的確不太理解這句話。
了解我的朋友應(yīng)該知道,我對(duì)語言是沒什么感情的,談不上喜歡亦或是討厭。生活中有太多值得去”喜愛“的東西,一本好書、一部電影都能讓我沉醉,編程語言實(shí)在排不上號(hào)。所以,當(dāng)我指出JS的一些問題時(shí),只希望大家能夠正視這些問題。一個(gè)人成熟的標(biāo)志是你是否可以客觀看待某個(gè)問題,而不是一味的袒護(hù)與自我麻醉。你大可不必一聽到語言的問題就如同坐了穿天猴般蹦的老高老高,語言而已,它欲成仙我們不能左右;它要跌落神界,我們也無能為力。
沒有語言沒有缺陷。
如果JS那么優(yōu)秀,為什么現(xiàn)在的ES新標(biāo)準(zhǔn)瘋狂迭代,不斷借鑒其他語言,越來越面向?qū)ο蠡?#xff1f;
拋開作為前端開發(fā)者出于保護(hù)自己飯碗那點(diǎn)小心思,我們應(yīng)該理智的承認(rèn),JS這個(gè)語言在ES新標(biāo)準(zhǔn)普及前,它確實(shí)不如現(xiàn)代流行的其他語言。甚至是對(duì)于絕大多數(shù)的開發(fā)者來說,JS引以為傲的“靈活性”和原型鏈的設(shè)計(jì)模式反而是一種負(fù)擔(dān)。
作為一個(gè)在Jquery還未普及就開始手寫原生JS的開發(fā)者,今天確實(shí)想和大家聊聊JS面向?qū)ο蟮囊恍﹩栴}。
JS是否應(yīng)該支持面向?qū)ο?#xff1f;或者說,我們是否應(yīng)該用面向?qū)ο蟮乃季S來編寫JS代碼?
必須肯定的是JS本身就不是為面向?qū)ο蠖恼Z言,這一點(diǎn)同Java是有本質(zhì)區(qū)別的,所以它不能很好的支持面向?qū)ο笫菬o可厚非的。
但這里要糾正一個(gè)誤區(qū):JS是可以支持面向?qū)ο蟮?#xff0c;只不過它和經(jīng)典的面向?qū)ο髮?shí)現(xiàn)是有差異的。JS用ES5就可以模擬面向?qū)ο?#xff0c;它不是用Class來組織的,而是用原型鏈來“模擬”的。
但用原型鏈來模擬Java、C#中經(jīng)典的OO模型是相當(dāng)丑陋的,所以才有了ES6的Class。但ES6中的Class也僅僅是語法糖,在本質(zhì)上它依然是用ES5的機(jī)制來模擬的類。
在這個(gè)ES5像ES6、7、8、9新標(biāo)準(zhǔn)過度的特殊時(shí)期,對(duì)于JS生態(tài)其實(shí)是一件很尷尬的事情。
由于ES6標(biāo)準(zhǔn)雖然已經(jīng)非常普及了,但大量的庫由于早期沒有Class類的支持,所以依然保持著ES5中半面向?qū)ο?#xff0c;半過程式的編程方式。而我們現(xiàn)在在編程時(shí)構(gòu)建復(fù)雜的業(yè)務(wù)時(shí),必然又需要使用Class,當(dāng)用ES6的Class思維去調(diào)用這些“不倫不類”的庫時(shí),這就造成了“割裂”。
來看一個(gè)使用Sequelize操作MySQL數(shù)據(jù)庫定義Model模型時(shí)的典型例子:
以上代碼的邏輯非常簡(jiǎn)單,我們有三個(gè)模型對(duì)象需要實(shí)現(xiàn),但是這3個(gè)模型中有大量的重復(fù)屬性,就是在ArtBase中定義image、content、pubdate等屬性。那么按照通常的思維,我們需要有一個(gè)基類,這個(gè)基類包含了以上屬性,那么子類(Movie、Music、Sentence)需要繼承這個(gè)基類,才能避免在每個(gè)子類中都定義image、content、pubdate的屬性;此外,Movie、Music、Sentence還有一個(gè)公共的like方法,這個(gè)方法也需要定義在基類上。
在Sequelize中,要定義一個(gè)模型,必須使用define這種函數(shù)調(diào)用的方式來產(chǎn)生一個(gè)模型。而在define的時(shí)候是不能夠在模型中直接定義方法的,所以我們需要在define返回模型的prototype上添加like方法。
而Music由于有自己獨(dú)特的url屬性,所以他在繼承ArtBase后,還需要在構(gòu)造函數(shù)里用this.url 來添加屬性;而根據(jù)ES6 的Class規(guī)定,在使用this前,必須先調(diào)用super。我相信絕大多數(shù)熟悉面向?qū)ο蟮耐瑢W(xué),都不喜歡這種奇葩的寫法。如果你覺得還好,可以對(duì)比下下面Python版本的實(shí)現(xiàn):
4個(gè)Class,代表了基類、Music、Sentence、Movie。我相信即使你完全不了解Python,這樣的定義也能一看就明白,不要說我偏愛Python的風(fēng)格,這不是語言風(fēng)格的問題,而是語言機(jī)制的問題。換做Java、PHP等任何現(xiàn)代的OO語言,一樣是類似于Python這樣的寫法。
以上兩段代碼只是節(jié)選簡(jiǎn)化后的示例代碼,而在真實(shí)的業(yè)務(wù)中,由于類的復(fù)雜性,兩個(gè)版本的代碼優(yōu)雅性、可讀性差距越來越大。通過對(duì)比Lin CMS的KOA版和Python版本可以很明顯的看到語言特性上的差距。實(shí)現(xiàn)整個(gè)框架相同的功能,Python版本的代碼量只有JS的一半左右。
那為什么兩個(gè)版本的差距會(huì)這么大呢?ES6不是支持Class嗎?
仔細(xì)觀察上面兩端代碼,你會(huì)發(fā)現(xiàn),最根本的原因在于Sequelize是使用define這種工廠模式來創(chuàng)建的Class,但Python版本不同,它是直接可以定義一個(gè)Class。
那么為什么Sequelize不能直接定義一個(gè)模型基類呢?是現(xiàn)在做不到嗎?不是。最本質(zhì)的原因還是在于Sequelize這個(gè)庫早期由于ES6沒有普及,他本身底層就不是用面向?qū)ο蟮乃枷雭順?gòu)建的,而現(xiàn)在由于面向?qū)ο蟮钠占?#xff0c;它又想要支持面向?qū)ο?#xff08;define返回的就是一個(gè)ES6的Class)。這就造成了“割裂”,顯得不倫不類。
這樣的例子不只是存在于Sequelize中,大量的經(jīng)典庫依然是老舊的ES5的寫法。不要小看這個(gè)問題,沒有很好面向?qū)ο笾С值膸旎静痪邆鋽U(kuò)展性。
當(dāng)一個(gè)被封裝好(無法更改源碼)的庫,如果它的提供的功能不符合我們的需求怎么辦?有一定面向?qū)ο缶幊探?jīng)驗(yàn)的同學(xué)應(yīng)該知道,如果庫均是以Class的方式提供的,那么我們可以繼承這個(gè)Class,然后通過方法重載或者方法覆蓋的方式來重寫某個(gè)關(guān)鍵的方法,從而實(shí)現(xiàn)自己的邏輯。
但事實(shí)上,由于大量的庫都不是以Class的方式來構(gòu)建的,我們根本無法在庫的外部通過這種繼承的方式來修改庫的默認(rèn)行為。這是一場(chǎng)災(zāi)難,而且短時(shí)間無法解決。
那是否由于這些原因,我們?cè)诰帉慗avaScript代碼時(shí)就不應(yīng)該使用面向?qū)ο蟮姆绞絹順?gòu)建?肯定不是。面向?qū)ο笫且粋€(gè)無法逃避的思維,它是解決復(fù)雜應(yīng)用的必備工程手段。
反過來看,你現(xiàn)在能想到某種替代面向?qū)ο蟮钠渌行侄螁?#xff1f;函數(shù)式編程?有些鼓吹函數(shù)式編程(FP)的人根本沒有真實(shí)的用函數(shù)式編程開發(fā)過完整的項(xiàng)目或者應(yīng)用。JS也根本不是一個(gè)函數(shù)式編程的語言。
Scala可以算作一個(gè)函數(shù)式編程語言,但有多少人拿Scala來構(gòu)建一個(gè)大型的應(yīng)用?面向?qū)ο竽芰餍羞@么久自然是有它的道理的。很多人鼓吹函數(shù)式編程只不過是玩弄一些對(duì)于絕大多數(shù)人陌生的概念,從而體現(xiàn)自己的與眾不同。
函數(shù)式編程的思維并不是沒有用,但函數(shù)式編程更多的是用于局部的代碼塊或者解決某個(gè)方向的問題,很少被全面用于整個(gè)應(yīng)用中。比如Map/Reduce就是比較經(jīng)典的函數(shù)式思維。
很多前端開發(fā)者認(rèn)為,面向?qū)ο笾皇欠?wù)器端需要使用,前端是不要的。那么,什么是服務(wù)端,什么是前端?為什么服務(wù)端需要而前端不需要呢?僅僅是服務(wù)端比前端多了一個(gè)操作數(shù)據(jù)/數(shù)據(jù)庫的能力?所以前端就不需要?還是因?yàn)榍岸擞幸徊糠质亲鯱I層面的所以不需要?
恐怕給出這種結(jié)論的人也說不清楚。事實(shí)上,前端和服務(wù)器的界限已經(jīng)變的很模糊了,特別是NodeJS讓JS脫離了瀏覽器后,這個(gè)界限更加的模糊,你根本無法界定哪些功能必須是前端工程師做,哪些必須是服務(wù)工程師來做。
前端的業(yè)務(wù)已經(jīng)越來越復(fù)雜了,除了不能直接操作數(shù)據(jù)和數(shù)據(jù)庫,前端幾乎和服務(wù)端沒有太大的區(qū)別。面向?qū)ο蠼?jīng)過幾十年的實(shí)踐,已經(jīng)被無數(shù)經(jīng)典的案例證明是最有效的代碼構(gòu)建手段。TypeScript的流行一部分原因是因?yàn)镴S沒有類型約束,而TS解決了這個(gè)問題;但另一方面卻是因?yàn)門S非常像C#,而C#的確是比Java還要經(jīng)典的面向?qū)ο笳Z言。使用TS天然的面向?qū)ο筇匦詠順?gòu)建復(fù)雜的應(yīng)用是一個(gè)很好的選擇。
也許TS不是構(gòu)建面向?qū)ο笄岸藨?yīng)用的唯一手段,但用面向?qū)ο蟮乃季S來編寫前端代碼必定是大勢(shì)所趨。
有人說JavaScript在設(shè)計(jì)之初本就只是為了在瀏覽器里做做簡(jiǎn)單的”特效“,比如跑馬燈、動(dòng)態(tài)色彩等粗糙的效果,是我們太”貪心“賦予了JavaScript太多的責(zé)任。這個(gè)論述承認(rèn)了JS在沒有普及ES新特性前確實(shí)不如其他語言,但依然不承認(rèn)Web前端其實(shí)被JS這個(gè)語言“劫持”了。現(xiàn)今的情況下,找不到替代JS的前端方案。
事實(shí)上,前端之所以選擇JS不是因?yàn)樗卸鄡?yōu)秀,而是因?yàn)镴S綁架了整個(gè)Web前端。即使是NodeJS的流行也不是因?yàn)樗銐虻膬?yōu)秀和不可替代亦或是有非常強(qiáng)的特點(diǎn),而僅僅是因?yàn)镴avaScript在前端的統(tǒng)治性,“反推”出來我們需要有脫離瀏覽器的JS環(huán)境,從而誕生了Node。
再拿NodeJS的一大用處——前端工程化來看:前端工程化不能用Python、Java嗎?當(dāng)然能,前端工程化的基礎(chǔ)在于對(duì)文件的讀寫能力,哪個(gè)服務(wù)端語言不具備文件讀寫能力?糾其原因依然是因?yàn)榍岸俗钍煜さ氖荍S,所以需要用JS來讀寫文件實(shí)現(xiàn)前端工程化。
在語法層面上,JS的特性也讓很多函數(shù)的接口設(shè)計(jì)顯得及其怪異:
其實(shí)就是一段普通的函數(shù)調(diào)用,但JS的語言特性,讓它無法避免這種嵌套式的傳參形式。可閱讀性極差。如果你要昧著良心說,“好”,那我也很無奈。
那我們就不應(yīng)該深入學(xué)習(xí)JS或者NodeJS了嗎?不,對(duì)于前端開發(fā)者來說,還是得學(xué)。既然JS綁架了整個(gè)Web前端,你能有什么辦法?我們畢竟是普通開發(fā)者,隨大流總不會(huì)錯(cuò)。我們依然需要面試、找工作,依然需要靠JS生活。
所以,被xx了咋辦呢?躺下來享受就好。就像Lin CMS,如果按照我的意愿,我根本不想開發(fā)KOA版本,然而人多力量大,前端人就是多,那就必須搞個(gè)KOA版本,讓大家能夠用一個(gè)語言完成前端和服務(wù)端。
有時(shí)候,JS綁架了整個(gè)Web前端反而也挺好的。服務(wù)端能選擇的語言太多了,java、python、php、go、c#,有同學(xué)總是問我,我到底學(xué)什么語言,我總是說不清楚,挺費(fèi)事的。
然而前端就沒這個(gè)煩惱,JavaScript,你沒得選擇。這真是件很美妙的事兒呢。
我以前總是覺得學(xué)一個(gè)語言并不是一件太費(fèi)事兒的事情,所以我總是告訴前端開發(fā)者,如果你想做服務(wù)端最好的選擇是Python而不是JS。但我覺得,我犯了2個(gè)錯(cuò)誤,一是我不應(yīng)該拿我10年的開發(fā)經(jīng)驗(yàn)來對(duì)標(biāo)初學(xué)編程的前端開發(fā)者。二是,我忽略了找工作這個(gè)最重要的事情。
NodeJS依然是前端進(jìn)階到全棧成本最低的語言。既能加深JS語言的理解,反哺前端開發(fā)、又能給前端未來沒落后或者競(jìng)爭(zhēng)太激烈時(shí)(我說假如),留給自己一條退路、還能增強(qiáng)找工作的籌碼、還能自己獨(dú)立開發(fā)一個(gè)完整的項(xiàng)目,關(guān)鍵是還沒有語言障礙。
一個(gè)語言要想精通還是太難了。至少編程的前五年接觸第二語言不是一件太好的事情。所以這次給《舊島》小程序做的服務(wù)端,我選擇的還是前端一體化的語言Node.js。詳細(xì)的課程內(nèi)容在后續(xù)的文章中給出。
我的課依然是我的風(fēng)格,業(yè)務(wù)只是個(gè)套子,真正讓人高潮的還是編程思維和JavaScript語言的本質(zhì)以及異步編程模型。
最后給大家留個(gè)作業(yè),也是在新課程中編寫校驗(yàn)器的時(shí)遇到的一個(gè)問題:
如何查找一個(gè)Class實(shí)例對(duì)象以及其所有父類上指定名稱前綴的自定義屬性名和自定義方法名?
有點(diǎn)抽象,我們給出具體的題干代碼:
A、B、C是三個(gè)一次繼承的類。你需要編寫一個(gè)findMembers函數(shù),傳入屬性名的前綴name,和方法的前綴名validate;查找全部的以name和validate開頭的屬性和方法名稱。函數(shù)的返回結(jié)果應(yīng)該是nameA、nameB、nameC和validateA、validateB、validateC。
注意,我們尋找的是自定義方法和屬性,所以只能返回這6個(gè)名稱字符串,不能包含js對(duì)象的內(nèi)置方法。
這個(gè)問題不難也不簡(jiǎn)單,需要對(duì)原型鏈有一定的了解。這個(gè)問題放到Java、Python、C#中就是幾句代碼,因?yàn)檫@些語言已經(jīng)內(nèi)置了查找方法。但JS,我沒找到內(nèi)置的方法。
同學(xué)們可以把代碼直接截圖發(fā)到公眾號(hào)后臺(tái),我從最好的解決方法中挑選一位同學(xué),贈(zèng)送一本我很喜歡的《黑客與畫家》。有時(shí)間寫篇文章,單獨(dú)聊聊。
愛我,請(qǐng)關(guān)注我的公眾號(hào):
總結(jié)
以上是生活随笔為你收集整理的前端判断session对象是否为空_谈谈JavaScript这个语言与前端是否需要面向对象?...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 最长回文子串动态规划_九章算法 | 微软
- 下一篇: ssm把图片保存到项目中_项目中的图片跨