我曾經出了一個面試題目如下:name == "John" 和 name.Equals("John") 有什麼差別?
看起來沒什麼不一樣的東西,卻還是有些學問在裡面,而什麼時候要用==,什麼時候要用Equals呢?而Javascript的===和==之間倒底有什麼問題呢?
我們從「值」開始說起。
一般而言,程式語言會透過兩種方法來使用變數:變數的值、變數的型態還有變數存在的位址,什麼意思呢:假設我們有兩個數字,都是100,在系統裡,他會劃出兩個不同的記憶體位址去存放。而在某些比較嚴謹的說法裡,這兩個數字「相同」有兩個不同的意思:
a. 他們都是100,所以是相同的
b. 他們在系統的記憶體位址都一樣,所以是相同的
下面有個範例:a和b都是100,但在不同的意義下,會產生不同的結果。
換句話話,在程式開發時,左右兩邊相等,有三種意思:
回到原本的問題,==和Equals有什麼差別?簡化後的答案是:==是一個操作,用來比對左右邊的「值」是否相等,而這個「值」依比對的對象而定。而Equals是一個虛擬方法,每個物件都可以依需要去設計不同的Equals方法,例如字串比對,就可以包含比對字串是否要乎略大小寫,是否要考慮編碼...等等參數。
userName.Equals(userName.AdminUsername, StringComparison.OrdinalIgnoreCase);
另一個問題是,因為Equals是一個方法,所以他至少要參考到一個物件,如果name是一個空物件,那Equals就不存在了。
為什麼要說這些東西呢?
Javascript做為一個弱型態的語言,自然沒有那麼多問題,但也在它演進到物件化的過程裡,開始有些新的東西產出,它很有趣,叫===。
W3CSchool是這麼說的:
== equal to
=== equal value and equal type
我認為Javascript初期的自由奔放影響了它後續的發展,以致於之後它必需用更多的方法去讓==或===符合他應有的行為:
有部份的開發人員甚至認為應該使用===。
但...現在有TypeScript了,這個做為Javascript的超集合,並且提供了物件導向的語法,那應該要繼續使用===嗎?
這應該是一個開放的題目,無論是那種方法,都應該要尋求共識,而不是「大家都這樣做」帶過。這些東西在語意上可能都相同,但實作上卻可能會產生不同的結果。如果在程式裡突然看到一個Equals,或者突然看到一個==,會有什麼原因呢?是因為他不需要知道它的內容?還是有什麼可能存在的問題?這些都應該在Code review的時候思考一下。
在我的看法裡,如果只是值的比對,應該用==,而如果是針對內容或物件做比對,用Equals()或===。
最後宣導一下:不要再用這種方法比對字串了:
input.ToUpper() == SomeString;