今天瀏覽一些技術網站,看到這個題目。雖然覺著代碼這麼寫的可能性低之又低,但是卻也考驗對js瞭解的程度。 在 JavaScript 中 (a ==1 && a== 2 && a==3) 可能為 true 嗎?解釋說nothing is impossible! 這裡是兩個可能的答案: 運行代碼 運行代碼 ...
今天瀏覽一些技術網站,看到這個題目。雖然覺著代碼這麼寫的可能性低之又低,但是卻也考驗對js瞭解的程度。
在 JavaScript 中 (a ==1 && a== 2 && a==3) 可能為 true 嗎?解釋說nothing is impossible!
這裡是兩個可能的答案:
<script> const a = { i: 1, toString: function () { return a.i++; } } if(a == 1 && a == 2 && a == 3) { console.log('Hello World!'); } </script>
<script> const a = { i: 1, valueOf: function () { return a.i++; } } if(a == 1 && a == 2 && a == 3) { console.log('Hello JavaScript!'); } </script>
最根本的還是強制類型轉換。類型==,===運算符和強制轉換:
先看個表達式:
<script> var res = "1.0e0" == { valueOf: function() { return true; } }; console.log(res); </script>
是的,這個結果也是 true。
對於這個表達式我們能夠註意到:
它們的類型是不一樣的。原因是在運算的時候進行了強制轉換。在比較之前,它們被轉換成了數字。
字元串”1.0e0“被解析成數字1,而匿名對象通過調用自身的valueOf方法得到true,然後再轉換成數字1。
這也是a可以同時為1,2,3的原因。
我們需要知道的是:
1、如果表達式兩邊的數據類型不一致,==運算符兩邊會進行強制轉換;
2、此對象在被強制轉換時,會自動優先調用了自身的valueOf方法
3、如果此對象沒有valueOf方法,則會繼續嘗試調用toString方法
4、如果將==運算符改成===運算符,則不會強制轉換;
5、如果表達式兩邊數據類型一致,==運算符和===運算符返回的結果是一致的
下圖為==運算符針對不同類型參數的強制轉換規則:
規則看著挺複雜,不幸的是,它其實也是這麼複雜。所以在比較操作中,如果不同類型進行比較,不建議使用==運算符,而是使用嚴格相等===運算符,因為使用嚴格相等運算符讀者會非常清晰地知道:在比較中沒有涉及任何強制轉換。否則,你需要讀者準確的記住這些強制轉換規則以解讀代碼的行為。
另外一個增加代碼可讀性的方法就是顯示的進行數據類型轉換:
代碼1:
var today = new Date(); if(form.month.value == (today.getMonth() + 1) && form.day.value == today.getDate()){ //happy birthday... }
代碼2:
var today = new Date(); if(+form.month.value == (today.getMonth() + 1) && +form.day.value == today.getDate()){ //happy birthday... }
很顯然,代碼2更加清晰地向讀者傳達了代碼在做什麼樣的轉換,它只是顯式的使用Number函數或者一元運算符 + 將值轉換為數字,而不要求讀者記住這些轉換規則。