js的類型轉化三兩事兒

在js中,類型轉換是一個被很是多人詬病的地方。新手看了會發矇,老手看了會頭疼。前端

類型轉換,又成爲強制類型轉換,主要區分爲顯式強制類型轉換隱式強制類型轉換面試

按我理解,類型轉換的意思就很明顯,就是當程序運行時須要此刻的變量的類型與變量的實際類型不符時,就會進行強制轉換,在一些靜態語言中,這個過程發生在編譯階段,或者乾脆就拋出錯誤。而在js中,這個轉換過程發生在運行時,因此你寫代碼的時候並不會意識到本身已經掉進坑裏了。函數

顯式強制類型轉換,簡單的說,就是你以爲你能夠明面上一眼看出來的,好比‘’ + number,+string,Boolean(value); 而隱式強制類型轉換就是反過來的意思。編碼

舉個栗子:code

var a = 'value';
if (a == true) {
  console.log('a is true');
} else if (a == false) {
  console.log('a is false');
}

按照正常的腦回路,通常人不會這麼寫。可是確實是有人會寫if (a == true) {...}這種語句,固然,後面的else if (a == false)是爲了節目效果加的。即使是這樣,a == true這種寫法也是不可取的。對象

最後的輸出是,兩個都不輸出。即在這個隱式強制類型轉換中,a即不會等於true, 也不會等於false。開發

首先解釋一下爲何a既不等於true, 也不等於false。按照正常人類的腦回路,應該是將a先轉換爲布爾值,而後再將兩個布爾值對比。這種狀況下,a轉成布爾值只能轉換成true或者false。要是這麼想,那你就是too young, too simple了字符串

當使用相等操做符==進行判斷時,將遵循如下規則(來自紅寶書):string

· 若是又一個操做數是布爾值,則在比較相等性以前先將其轉換爲數值(false轉換爲0,而true轉換爲1
· 若是一個操做數是字符串,另外一個操做數是數值,在比較相等性以前先將字符串轉換爲數值
· 若是一個操做數是對象,另外一個操做數不是,則調用對象的valueOf()方法,用獲得的基本類型值按照以前的規則進行比較
· null和undefined是相等的
· 要比較相等性以前,不能將null和undefined轉換成其餘任何值
· 若是一個操做數是NaN,則相等操做符返回false。
· 若是兩個操做數都是對象,則比較它們是否是同一個對象,是則返回true,不然返回false

因此就能夠知道上例中,轉換是如何進行的。首先兩個相等操做的操做數中都包含布爾值,先將布爾值轉換爲數值因此這裏true轉換爲1,false轉換爲0。接下來再次進行比較,此時兩對操做數中都包含一個字符串操做數,則將字符串轉換爲數值, a轉換爲數值是NaN,此時再次進行比較,因爲有一個操做數是NaN,按照規則,返回false。因此a既不等於true也不等於false。console

由上能夠看出,使用==進行條件判斷的時候是很是具備危險性的,尤爲是當其中一個操做數爲true的時候,若是另外一個操做數不爲布爾值,則頗有可能就掉進坑裏了。

那麼通常在判斷的時候怎麼去進行判斷比較好呢。我認爲儘可能不使用==操做符。使用===進行全等判斷,或者直接將你須要判斷的值丟進if判斷裏,好比if (a == true)能夠改爲if (a)或者if (!!a)這樣就能避開==操做符的坑了。若是必定要使用==進行比較,不用不舒服,則最好先將操做數進行顯式類型轉換爲同一類型的數據,再進行比較,

知其然就要知其因此然。
爲何if (a)if (!!a)就能夠避開==操做符的坑呢?它們進行強制類型轉換時的轉換規則又是怎樣的。

其實在if的判斷語句塊內,若是判斷值不是布爾值的話,會自動調用Boolean()函數進行布爾值的轉換。而!!則至關於一次Boolean()的值類型轉換了。因此在if的判斷語句裏直接放入判斷條件和顯式的將判斷條件進行轉換,其做用是同樣的。區別也只是在因而否對後續看代碼的人友好了,若是後面代碼維護多是接觸代碼不深的新手,則建議進行顯式的轉換。

由上面的解釋能夠知道if (a)if (!!a)if (Boolean(a))的做用是同樣的,因此這裏只要瞭解一下Boolean()函數的轉換規則就能夠了:

任何非空字符串爲true,空字符串('')爲false
任何非零數字值(包括無窮大)爲true,0和NaN爲false
任何對象爲true,null爲false
undefined爲false

以上規則來自紅寶書,部份內容省略

看以上的Boolean()函數的轉換規則,與咱們平常工做中所須要的類型轉換是很是契合的。
好比咱們廣泛會認爲並要求if能夠攔截空字符串,false,null,undefined,0與NaN

須要注意的是,雖然紅寶書上並沒明確指出,但三元運算符( ? : )使用的轉換規則也是Boolean()函數的轉換規則.

而除了條件判斷,在其餘一些操做裏也會出現類型轉換,好比關係操做符(<, >, <=, >=):

var a = '23';
var b = '3';
console.log(a < b); // true

上面這個轉換可能不少的前端開發工程師都掉進過坑裏並摸不着頭腦。
可能你也看出來了出現‘23’小於‘3’的緣由或許是在於它們都是字符串。若是關係操做符(<,>,<=,>=)兩邊都是字符串,則比較兩個字符串對應的字符編碼。'2'的字符編碼是50,而3的字符編碼是51,因此這裏出現了‘23’小於‘3’的狀況。

到這裏不少人都會驚歎一聲,並表示記住了此知識點。可是這樣每每是不夠的,你須要深挖下去,須要確切的瞭解關係操做符的轉換規則,才能確保不會再次掉進它的坑裏。

若是兩個操做數都是數值,則執行數值比較 若是兩個操做數都是字符串,則比較兩個字符串對應的字符編碼值
若是一個操做數是數值,則將另外一個操做數轉換爲一個數值,而後執行數值比較
若是一個操做數是對象,則調用這個對象的valueOf()方法,並用獲得的結果根據前面的規則進行比較
若是一個操做數是布爾值,則先將其轉換爲數值,而後再執行比較
若是一個操做數是NaN,undefined,則返回false
若是操做數爲null, '', 則轉換爲0進行比較

多看看紅寶書就會發現js中的類型轉換其實坑仍是不少的,還有一些加減乘除的操做符自己也會產生類型轉換的問題。可是基本問題不是太大,因此就不單獨拎出來了。

最後,一道思考題:

// do something ...
console.log(typeof a); // 'object'
console.log(a == false); // true

上面的對象爲何會等於false,這個題是以前刷到的一道面試題,可不是我瞎編的。。

最後,歡迎斧正,沒有仔細的準備,因此寫的少且雜,也是做爲本身的一個總結回顧吧。

相關文章
相關標籤/搜索