1. 程式人生 > >JavaScript七宗罪和一些槽點

JavaScript七宗罪和一些槽點

當下JavaScript越來越流行,成為長期霸語言榜前三的語言。但是實際上JavaScript是一個很醜陋有很多槽點的語言,這就是為什麼新出了那麼多框架(從jQuery到Vue)以及海爾斯伯格大大推出新流行語言的Type Script的直接原因,避免大家去直接用JavaScript寫程式碼。雖然這幾年隨著ECMAScript 6(ES6)推出,JavaScript逐漸變得好用起來,但是JavaScript確實一直存在這一些揮之不去的痛。

本文作何就來和大家一起細數下JavaScript的一些語言痛點,知短而成長也是成功法則之一。首先申明我們不是攻擊JS語言和JS的碼農們(惹不起),只是希望以此讓大家更加了解JS,寫出更好更高效的JS程式碼來。

1:有問題的ASI實施

ASI機制問題,現在存在爭議。JavaScript有一種稱為自動分號插入(ASI)的機制,如果需要,會自動在你的程式碼中插入分號。JS的語言結束可以使用分號;

doSomething();

但是分號可以省略,如果你不新增分號的話,ASI會自動判斷,並且自動給你新增上分號。

JavaScript七宗罪和一些槽點

 

但是ASI實現是有問題的,如果不是熟悉ASI的機制,某些情況下ASI機制會破壞你的程式碼,在不該中斷地方給你中斷,該中斷地方又不會中斷,就很尷尬了,而且出問題來很難除錯。

你可以選擇忽略不用它,自己一直新增分號。如果你不想手動敲,則必須熟悉ASI,避免寫出引起歧義的語句,以免受邊緣情況的影響。

JavaScript七宗罪和一些槽點

 

2:有一個怪異的數字型別

與許多其他語言相反,JavaScript有一種稱叫做數字型別的單數數字型別。這種型別用於整數和浮點數,對於許多開發人員來說是違反直覺的,絕大多數開發人員都是熟悉的:整數和十進位制數字之間有明確區別的語言。

JavaScript七宗罪和一些槽點

 

碼農需要時常提醒自己到將所有數值操作基於浮點數來處理,並且還需要使用Math物件進行舍入和查詢操作的floor()或round(),很多數字操作需要自己專門寫函式,很麻煩。下面是保留二位的小數的函式。

JavaScript七宗罪和一些槽點

 

此外,型別的數字限制只能使用53位整數,對於更大的整數,你可能需要獲取庫。

3:三個非值數字:Infinity,-Infinity和NaN

JavaScript有個邏輯"提示,並且繼續",無效或無意義的計算(例如除零)不會導致錯誤或丟擲異常,而是產生三個非實數值中的一個,實際上是數字型別:

JavaScript七宗罪和一些槽點

 

所以,JS處理數字非常麻煩,並且當涉及到計算繁重的程式時,很難以追蹤錯誤。還需要諸如isFinite,isInteger和isNaN之類的大量方法來做進行數字檢查。

4:兩個"空"型別:null和undefined

JavaScript七宗罪和一些槽點

 

JS事實上有兩種不同的null或nil型別,原意是為了更確定區分錯誤,但可能導致碼農在處理時候,反而會增加很多bug。

JavaScript七宗罪和一些槽點

 

通常,undefined指的是未初始化的變數或不存在的物件屬性,並且指向故意為空的變數或物件屬性null,但是如何確定他應該是null或者undefined是個問題。當涉及null用例時,typeof運算子會被破壞

typeof null; // "object"

5:破碎的抽象等式(==)演算法

這裡真的沒什麼好說的。 ==運算子背後的抽象等式演算法很滑稽,打破了平等和等價關係的數學概念。

JavaScript七宗罪和一些槽點

 

它不應該被使用。應該使用嚴格相等運算子===。

6:不可取的型別強制轉化

在處理動態變數和鬆散輸入時,你最終需要執行某種型別強制來完成某些操作。 JavaScript的問題在於引擎所做的隱式型別強制轉化是不可取的,非常規的,並且可能導致程式碼中出現大量錯誤。

例如,在混合字串和數字時,+運算子可能會導致一些意外結果:

13 + !0; // 14

"13" + !0; // '13true

更不用說所有這些都是有效但令人費解的語言表達:

JavaScript七宗罪和一些槽點

 

作為開發人員,你需要通過包裝類建構函式Number,Boolean和String或某些內建解析方法來堅持顯式型別強制。

好訊息是,被強制轉化的值非常容易和直觀地記住:"false,null,undefined,NaN,0和''(空)都是邏輯假,其他一切都是true"。

7:var關鍵字和函式範圍

在ES6之後,這已不再是一個問題了。但這是對語言設計不良的證明,十多年來程式設計師不得不接受這樣一個事實,即宣告的一個變數是全域性性變數。

JavaScript七宗罪和一些槽點

 

基本上,你使用var將全域性變數引入你的程式中,如果你不小心並且沒有真正的塊變換範圍,這使得理解一些簡單的方法就像使用範圍一樣令人費解。

在ES6之後,現在你應該完全停止使用var,而是使用提供常規塊作用域的let和const,並在程式碼開頭引入use strict指令,以防止意外的全域性變數宣告和其他有問題的執行時行為。

其他一些不是很重要的槽點

簡而言之,下面這些只是一些容易遇到而且有學習曲線的小錯誤,或者只是JavaScript獨特語言設計的一個特點,它具有豐富的靈活性和複雜性:

複雜和不良的繼承模型

複雜使用this關鍵字

標準庫不佳

我認為任何從Java或C#等語言進入JavaScript的程式設計師都搞不清JS語言混亂的類語法和用於實現類的複雜物件模型。其中大部分是由於設計不合理的約定和語法決策以適應企業開發人員,因為實際上JavaScript基於原型,而不是類,它的語法應該反映出來,但它確實增加了大多數現有開發人員熟練使用該語言的複雜性。

此外,執行JavaScript的執行時和併發模型在傳統程式語言中是相當獨特的,因為所有JS程式碼都是在事件迴圈執行時中使用事件驅動的非阻塞非同步I/O執行的。

最後吐槽的是JavaScript這個名字也是剛開始蹭人熱度,後來又非法的存在(JavaScript商標權在Oracle手裡),所以避免在自己的產品或者宣傳中使用它(已經有開發者收到Oracle的律師函哦),用JS或者正式的名字ECMAScript來替代。