空話不多說,我們先來看第一個例子吧。
某天,我遇到了如許一個問題:給出變量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如許劃定:
(1)假如Type(x)是数字,Type(y)是字符串,則返回x == ToNumber(y)的效果
(2)假如Type(x)是字符串,Type(y)是数字,則返回ToNumber(x) == y的效果
關於其他範例和布爾範例的比較,範例11.9.3.6.7如許劃定:
(1)假如Type(x)是布爾範例,則返回ToNumber(x) == y的效果
(2)假如Type(y)是布爾範例,則返回x == ToNumber(y)的效果
關於null和undefined來講,ES5範例11.9.3.2.3如許劃定:
(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轉換為数字。