JavaScript中通常分為兩種類型轉換, “隱式強制類型轉換”(implicit coercion)和“顯式強制類型轉換”(explicit coercion)。
下面所有代碼的源碼可以。
一、強制轉換為字串(ToString)
1)ToString
基本類型值的字串化規則為:null轉換為"null", undefined轉換為"undefined", true轉換為"true"。 數位的字串化則遵循通用規則, 不過那些極小和極大的數位使用指數形式:
// 1.07 連續乘以七個 1000 var a = 1.07 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000; // 七個1000一共21位元數字 console.log(a.toString); // "1.07e21"對普通物件來說, 除非自行定義, 否則toString(Object.prototype.toString())返回內部屬性[[Class]]的值
2)JSON
JSON.stringify(..)在物件中遇到undefined、function和symbol時會自動將其忽略, 在陣列中則會返回null(以保證單元位置不變)。
如果物件中定義了toJSON方法, JSON字串化時會首先調用該方法, 然後用它的返回值來進行序列化。
二、強制轉換數位(ToNumber)
1)ToNumber
1. true轉換為1, false轉換為0;
2. undefined轉換為NaN, null轉換為0;
3. "", 轉換為0。 處理失敗時返回NaN。
4. ToNumber對以0開頭的十六進位數並不按十六進位處理。
2)物件
物件(包括陣列)會首先被轉換為相應的基本類型值, 如果返回的是非數字的基本類型值, 則再遵循以上規則將其強制轉換為數位。
為了將值轉換為相應的基本類型值, 抽象操作ToPrimitive會首先(通過內部操作DefaultValue)檢查該值是否有valueOf方法。
如果有並且返回基本類型值, 就使用該值進行強制類型轉換。 如果沒有就使用toString的返回值(如果存在)來進行強制類型轉換。
var a = { valueOf: function { //先執行valueOf return "42"; } }; var b = { toString: function { //再執行toString return "42"; } }; var c = [4, 2]; c.toString = function { return this.join(""); // "42" }; Number(a); // 42 Number(b); // 42 Number(c); // 42 Number(""); // 0 Number([]); // 0 Number(["abc"]); // NaN三、強制轉換布林值(ToBoolean)
1)假值(falsy value)
可強制類型轉換為false。 包括undefined、null、false、+0、-0、NaN、""。
undefined、null、false、+0、-0、NaN、""2)真值
、{}和function{}都不在假值列表中。
、{}和function{}四、顯式強制類型轉換
1)奇特的~運算子
~x大致等同於-(x+1)。
用~~來截除數字值的小數部分~~中的第一個~執行ToInt32並反轉字位, 然後第二個~再進行一次字位反轉, 即將所有字位反轉回原值, 最後得到的仍然是ToInt32的結果。
//奇特的~ var a = "Hello World"; if (~a.indexOf("lo")) { //如果未找到就返回-1, (-1+1)=0就是false // 找到匹配! } //~~ Math.floor(-49.6); // -50 ~~-49.6; // -492)顯式解析數位字串
解析允許字串中含有非數位字元, 解析按從左到右的順序, 如果遇到非數位字元就停止。
轉換不允許出現非數位字元, 否則會失敗並返回NaN。
var a = "42"; var b = "42px"; Number(a); // 42 parseInt(a); // 42 Number(b); // NaN parseInt(b); // 42解析字串中的浮點數可以使用 parseFloat(..)函數。
非字串參數會首先被強制類型轉換為字串(執行toString方法)。
parseInt(0.000008); // 0 ("0" 來自於 "0.000008") parseInt(0.0000008); // 8 ("8" 來自於 "8e-7") parseInt(false, 16); // 250 ("fa" 來自於 "false") parseInt(parseInt, 16); // 15 ("f" 來自於 "function..") parseInt("0x10"); // 16 parseInt("103", 2); // 2五、隱式強制類型
1)字串和數位之間的隱式強制類型轉換
如果+其中一個運算元是字串則執行字串拼接;否則執行數位加法。
如果其中一個運算元是物件(包括陣列),
2)隱式強制類型轉換為布林值
以下情況, 非布林值會被隱式強制類型轉換為布林值, 遵循ToBoolean 抽 象操作規則。
1. if (..)語句中的條件判斷運算式。
2. for ( .. ; .. ; .. )語句中的條件判斷運算式(第二個)。
3. while (..)和do..while(..)迴圈中的條件判斷運算式。
4. ? :中的條件判斷運算式。
5. 邏輯運算子||(邏輯或)和&&(邏輯與)左邊的運算元(作為條件判斷運算式)。
六、寬鬆相等和嚴格相等
常見的誤區是“ == 檢查值是否相等, === 檢查值和類型是否相等”。 聽起來蠻有道理, 然而 還不夠準確。
正確的解釋是:“ == 允許在相等比較中進行強制類型轉換, 而 === 不允許”
1)字串和數位之間的相等比較
1.如果 Type(x) 是數字, Type(y) 是字串, 則返回 x == ToNumber(y) 的結果。
2.如果 Type(x) 是字串,
2)其他類型和布林類型之間的相等比較
1.如果 Type(x) 是布林類型, 則返回 ToNumber(x) == y 的結果。
2.如果 Type(y) 是布林類型, 則返回 x == ToNumber(y) 的結果。
3)null 和 undefined 之間的相等比較
1.如果 x 為 null , y 為 undefined , 則結果為 true 。
2.如果 x 為 undefined , y 為 null , 則結果為 true 。
4)物件和非物件之間的相等比較
1.如果 Type(x) 是字串或數位, Type(y) 是對象, 則返回 x == ToPrimitive(y) 的結果。
2.如果 Type(x) 是物件, Type(y) 是字串或數位, 則返回 ToPromitive(x) == y 的結果。
var a = "abc"; var b = Object(a); // 和new String( a )一樣 a === b; // false //b 通過 ToPromitive 進行強制類型轉換(也稱為“拆封”, unboxed或者unwrapped) , 並返回標量基本類型值 "abc" , 與 a 相等。 a == b; // true //null和undefined不能夠被封裝(boxed), Object(null)和 Object(undefined) 均返回一個常規物件。 var a = null; var b = Object(a); // 和Object一樣 a == b; // false var c = undefined; var d = Object(c); // 和Object一樣 c == d; // false //NaN能夠被封裝為數位封裝物件, 但NaN不等於NaN var e = NaN; var f = Object(e); // 和new Number( e )一樣 e == f; // false5)假值的相等比較
假值, 就是上面ToBoolean中提到的假值。
"0" == false;//true 按照2)和1)的規則 false == 0;//true 按照2)的規則 false == "";//true 按照2)和1)的規則 false == ;//true 按照4)2)1)的規則 "" == 0;//true 按照1) "" == ;//true 按照4)的規則 0 == ;//true 按照4)1)的規則 == !// true !執行後的值是false6)安全運用隱式強制類型轉換
1.如果兩邊的值中有true或者false, 千萬不要使用==。
2.如果兩邊的值中有、0或者"" , 儘量不要使用==。
7)比較圖表
dorey提供的一張線上圖表。