廢話很少說,咱們先來看第一個例子吧。
某天,我遇到了這樣一個問題:給出變量a和b的定義,使下面三個語句的輸出結果都爲true。數組
console.log(a<b); console.log(a==b); console.log(a>b);
看到題目的我第一反應是懵逼的,還有這樣的操做???而後一開始的思路是往各類神奇的值上面找,好比undefined,null,NaN,「」
這樣的值,天然是沒有獲得想要的結果了。
但事實上,真的存在。來看代碼:函數
function A(){ this.a = 1; } A.prototype = { toString: function(){ return this.a += 2; } } var a = new A(); var b = 5; console.log(a < b); console.log(a == b); console.log(a > b);
上面的代碼不難理解:變量a是經過構造函數A建立的對象,變量b就是一個很簡單的數值。一開始,由於a是經過構造函數A建立的對象,因此值爲1.而後每一次在執行 console.log()
的時候,會調用一次A的toString
方法。因此,在第一個console.log()
的時候,a的值變成了3,而b的值是5,因此a<b
爲true
;第二個console.log()
的時候,a的值變成了5,而b的值仍是5,因此a=b
爲true
;第三個console.log()
的時候,a的值變成了7,而b的值依舊是5,因此a>b
爲true
。
通過上面的分析,咱們彷佛打開了一個新世界的大門,這裏涉及到一個比較重要的概念:隱式類型轉換。在上面的例子裏,a和b是兩個徹底不同的類型,可是它們進行了比較,還得出告終果,這就說明有一個類型在比較的過程當中轉換成了另外一個類型。
這裏須要提到一些規範來幫助咱們更好的理解。
(小於大於的比較規則和相等是同樣的。)
對於字符串和數字來講,ES5規範11.9.3.4.5這樣規定:this
(1)若是Type(x)是數字,Type(y)是字符串,則返回x == ToNumber(y)的結果
(2)若是Type(x)是字符串,Type(y)是數字,則返回ToNumber(x) == y的結果
對於其餘類型和布爾類型的比較,規範11.9.3.6.7這樣規定:prototype
(1)若是Type(x)是布爾類型,則返回ToNumber(x) == y的結果
(2)若是Type(y)是布爾類型,則返回x == ToNumber(y)的結果
對於null和undefined來講,ES5規範11.9.3.2.3這樣規定:code
(1)若是x爲null,y爲undefined,則結果爲x == y
(2)若是x爲undefined,y爲null,則結果爲x == y
也就是說,null和undefined是相等的。
對於對象和非對象來講,ES5規範11.9.3.8.9這樣規定:對象
(1)若是Type(x)是字符串或數字,Type(y)是對象,則返回x == ToPrimitive(y)的結果
(2)若是Type(x)是對象,Type(y)是字符串或數字,則返回ToPrimitive(x) == y的結果
基本就是上面這幾種常見的類型的比較了。而後出現了一個咱們好像不太常見的東西:ToPrimitive()這個方法。咱們來簡單瞭解一下:
對象(或者數組)再進行比較或者類型轉換的時候,先會被轉換爲相應的基本類型值,而後再根據須要進行轉換。再轉換爲基本類型值的時候,抽象操做ToPrimitive會先檢查該值是否擁有valueOf()方法。若是有且返回基本類型值,就使用該值做爲基本類型值,若是沒有就使用toString()方法的返回值做爲基本類型值。
上面例子中的相等操做咱們使用了==
,而不是===
。對於這兩者的區別,咱們常常聽到的是,==
是不嚴格相等,只要值相等便可,而===
是嚴格相等,必須值和類型都相等才能夠。對於==
來講,類型不重要,也就是說在這個過程當中是包含了類型轉換的。因此,在YouDontKnowJS這本書中,給出的正確解釋是:字符串
==
容許在相等比較總進行強制類型轉換,而===
不容許。
而後咱們再來看第二個例子吧
題目是這樣的:[1]+[2]-[3]=?
此次打算先分析再給出答案,順便你們也能夠本身想一想結果是什麼。
首先咱們看到加減運算符左右兩邊的值都是數組,那前面提到過對於數組的處理。由於數組的valueOf()
操做沒法獲得簡單的基本類型值,因此會調用toString()
,這樣的話上面那個式子就變成了"1"+"2"-"3"=?
。如今這個式子相信你們都比較熟悉了,不過不知道會不會有人一時頭腦發熱,把答案想成了0。
而後咱們繼續往下,由於是加減操做符,因此咱們從左至右開始計算,"1"+"2"
這個結果究竟是3仍是12呢。那就記住簡單的一句話:若是有一個值是字符串,那麼就進行字符串拼接,不然進行數字加法。那麼很明顯,這裏是2個字符串,進行字符串拼接,獲得"12"
。
好了,到目前爲止,式子已經變成了"12"-"3"
了,這應該已經很明顯了吧,字符串拼接是確定不可能的,那就是進行數字運算了,那就是最簡單的12-3
了,因此最終結果就是9。
其實這個例子裏的經過加減運算符進行隱式類型轉換在咱們平常代碼中常常出現,只是可能你們沒有特別關注,好比a + ""
是把a轉換爲字符串;a - 0
是把a轉換爲數字。it