JavaScript 是一種動態型別語言,變數沒有型別限制,可以隨時賦予任意值。
var x = y ? 1 : 'a'
複製程式碼
上面程式碼中,變數 x
到底是數值還是字串,取決於另一個變數 y
的值。
y
為 true
時,x
是一個數值;y
為 false
時,x
是一個字串。這意味著,x
的型別沒法在編譯階段就知道,必須等到執行時才能知道。
轉換為 Number 型別
使用 Number()
函式,可以將任意型別的值轉化成數值。
下面分成兩種情況討論,一種是引數是原始型別的值,另一種是引數是物件。
原始型別值
原始型別值的轉換規則:
// 數值:轉換後還是原來的值
Number(324) // 324
// 字串:如果可以被解析為數值,則轉換為相應的數值
Number('324') // 324
// 字串:如果不可以被解析為數值,返回 NaN
Number('324abc') // NaN
// 空字串轉為0
Number('') // 0
// 布林值:true 轉成 1,false 轉成 0
Number(true) // 1
Number(false) // 0
// undefined:轉成 NaN
Number(undefined) // NaN
// null:轉成0
Number(null) // 0
複製程式碼
Number()
函式將字串轉為數值,要比 parseInt()
函式嚴格很多。基本上,只要有一個字元無法轉成數值,整個字串就會被轉為 NaN
。
parseInt('42 cats') // 42
Number('42 cats') // NaN
複製程式碼
上面程式碼中,parseInt()
逐個解析字元,而 Number()
函式整體轉換字串的型別。
另外,parseInt()
和 Number()
函式都會自動過濾一個字串前導和字尾的空格。
parseInt('\t\v\r12.34\n') // 12
Number('\t\v\r12.34\n') // 12.34
複製程式碼
使用 parseInt()
函式 在使用時要注意:
// 將二進位制的'1000'轉為十進位制的數值
parseInt('1000', 2) // 8
複製程式碼
物件
Number()
方法的引數是物件時,將返回 NaN
,除非是包含單個數值的陣列。
Number({a: 1}) // NaN
Number([1, 2, 3]) // NaN
Number([5]) // 5
複製程式碼
之所以會這樣,是因為 Number()
背後的轉換規則比較複雜。
-
呼叫物件自身的
valueOf()
方法。如果返回原始型別的值,則直接對該值使用Number()
函式,不再進行後續步驟。 -
如果
valueOf()
方法返回的還是物件,則改為呼叫物件自身的toString()
方法。如果toString()
方法返回原始型別的值,則對該值使用Number()
函式,不再進行後續步驟。 -
如果
toString()
方法返回的是物件,就報錯。
請看下面的例子:
var obj = {x: 1};
Number(obj) // NaN
// 等同於
if (typeof obj.valueOf() === 'object') {
Number(obj.toString());
} else {
Number(obj.valueOf());
}
複製程式碼
上面程式碼中,Number()
函式將 obj
物件轉為數值。背後發生了一連串的操作,首先呼叫 obj.valueOf()
方法, 結果返回物件本身;於是,繼續呼叫 obj.toString()
方法,這時返回字串 [object Object]
,對這個字串使用 Number()
函式,得到 NaN
。
預設情況下,物件的 valueOf()
方法返回物件本身,所以一般總是會呼叫 toString()
方法,而 toString()
方法返回物件的型別字串(比如 [object Object]
)。所以,會有下面的結果。
Number({}) // NaN
複製程式碼
如果 toString()
方法返回的不是原始型別的值,結果就會報錯。
var obj = {
valueOf: function () {
return {}
},
toString: function () {
return {}
}
}
Number(obj)
// TypeError: Cannot convert object to primitive value
複製程式碼
上面程式碼的valueOf()
和 toString()
方法,返回的都是物件,所以轉成數值時會報錯。
轉換為 String 型別
使用 String()
函式,可以將任意型別的值轉化成字串。
下面分成兩種情況討論,一種是引數是原始型別的值,另一種是引數是物件。
原始型別值
原始型別值的轉換規則:
// 數值:轉為相應的字串
String(123) // "123"
// 字串:轉換後還是原來的值
String('abc') // "abc"
// 布林值:true 轉為字串"true",false轉為字串"false"
String(true) // "true"
// undefined:轉為字串"undefined"
String(undefined) // "undefined"
// null:轉為字串"null"
String(null) // "null"
複製程式碼
物件
String()
方法的引數如果是物件,返回一個型別字串;如果是陣列,返回該陣列的字串形式。
String({a: 1}) // "[object Object]"
String([1, 2, 3]) // "1,2,3"
複製程式碼
String()
方法背後的轉換規則,與Number方法基本相同,只是互換了 valueOf()
方法和 toString()
方法的執行順序。
-
先呼叫物件自身的
toString()
方法。如果返回原始型別的值,則對該值使用String()
函式,不再進行以下步驟。 -
如果
toString()
方法返回的是物件,再呼叫原物件的valueOf()
方法。如果valueOf()
方法返回原始型別的值,則對該值使用String()
函式,不再進行以下步驟。 -
如果
valueOf()
方法返回的是物件,就報錯。
下面是一個例子:
String({a: 1})
// "[object Object]"
// 等同於
String({a: 1}.toString())
// "[object Object]"
複製程式碼
上面程式碼先呼叫物件的 toString()
方法,發現返回的是字串 [object Object]
,就不再呼叫 valueOf()
方法了。
轉換為 Boolean 型別
使用 Boolean()
函式,可以將任意型別的值轉化成布林值。
它的轉換規則相對簡單:除了以下五個值的轉換結果為 false
,其他的值全部為 true
。
-0
或+0
NaN
''
和""
(空字串)null
undefined
Boolean(0) // false
Boolean(NaN) // false
Boolean('') // false
Boolean(null) // false
Boolean(undefined) // false
複製程式碼
注意,所有物件(包括空物件)的轉換結果都是 true
,甚至連 false
對應的布林物件 new Boolean(false)
也是 true
。
Boolean({}) // true
Boolean([]) // true
Boolean(new Boolean(false)) // true
複製程式碼