JavaScript 是一種弱類(lèi)型的語(yǔ)言,也就是沒(méi)有類(lèi)型限制,變量可以隨時(shí)被賦予任意值。
同時(shí),在程序運(yùn)行過(guò)程中,類(lèi)型會(huì)被自動(dòng)確認(rèn)的。因此,這就是涉及到數(shù)據(jù)的類(lèi)型轉(zhuǎn)換。在 JS 的世界中,數(shù)據(jù)類(lèi)型轉(zhuǎn)換可以分為類(lèi)型的顯示轉(zhuǎn)換和隱式轉(zhuǎn)換。
JavaScript 中的顯示轉(zhuǎn)換
JS 中的顯示轉(zhuǎn)換主要指的就是手動(dòng)轉(zhuǎn)換為 數(shù)值、字符串、布爾值。
任意值轉(zhuǎn)換為數(shù)值
- 基本數(shù)據(jù)類(lèi)型值轉(zhuǎn)換為數(shù)值
原始類(lèi)型的值主要是字符串、布爾值、undefined和null,它們都能被Number轉(zhuǎn)成數(shù)值或NaN。
// 數(shù)值:轉(zhuǎn)換后還是原來(lái)的值
Number(324) // 324
// 字符串:如果可以被解析為數(shù)值,則轉(zhuǎn)換為相應(yīng)的數(shù)值
Number('324') // 324
// 字符串:如果不可以被解析為數(shù)值,返回NaN
Number('324abc') // NaN
// 空字符串轉(zhuǎn)為0
Number('') // 0
// 布爾值:true 轉(zhuǎn)成1,false 轉(zhuǎn)成0
Number(true) // 1
Number(false) // 0
// undefined:轉(zhuǎn)成 NaN
Number(undefined) // NaN
// null:轉(zhuǎn)成0
Number(null) // 0
- 對(duì)象轉(zhuǎn)換為數(shù)值
Number方法的參數(shù)是對(duì)象時(shí),將返回NaN,除非是包含單個(gè)數(shù)值的數(shù)值
Number({a: 1}) // NaN
Number([1, 2, 3]) // NaN
Number([5]) // 5
對(duì)象的轉(zhuǎn)換規(guī)則:
調(diào)用對(duì)象自身的valueOf方法。如果返回基本類(lèi)型的值,則直接對(duì)該值使用Number函數(shù),不再進(jìn)行后續(xù)步驟。
如果valueO方法返回的還是對(duì)象,則改為調(diào)用對(duì)象自身的toString方法。如果toStrin方法返回基本類(lèi)型的值,則對(duì)該值使用Numbe函數(shù),不再進(jìn)行后續(xù)步驟。
如果toStrin方法返回的是對(duì)象,就報(bào)錯(cuò)。
任意值轉(zhuǎn)化為字符串
- 基本類(lèi)型值
String(123) // "123"
String('abc') // "abc"
String(true) // "true"
String(undefined) // "undefined"
String(null) // "null"
- 對(duì)象
String方法的參數(shù)如果是對(duì)象,返回一個(gè)類(lèi)型字符串;如果是數(shù)組,返回該數(shù)組的字符串形式。
String({a: 1}) // "[object Object]"
String([1, 2, 3]) // "1,2,3"
對(duì)象轉(zhuǎn)換規(guī)則:
先調(diào)用對(duì)象自身的toString方法。如果返回基本類(lèi)型的值,則對(duì)該值使用String函數(shù),不再進(jìn)行以下步驟。
如果toString方法返回的是對(duì)象,再調(diào)用原對(duì)象的valueO方法。如果valueOf方法返回基本類(lèi)型的值,則對(duì)該值使用String函數(shù),不再進(jìn)行以下步驟。
如果valueOf方法返回的是對(duì)象,就報(bào)錯(cuò)。
任意值轉(zhuǎn)換為布爾值
使用 Boolean 函數(shù),以下六個(gè)值的轉(zhuǎn)換結(jié)果為false:
- undefined
- null
- -0
- 0 或 +0
- NaN
- ""(空字符串)
其他的任意值都是true,包括所有對(duì)象,即使是空對(duì)象
Boolean(new Boolean(false)) // true
甚至連false對(duì)應(yīng)的布爾對(duì)象new Boolean(false)也是true
JavaScript 中的隱式轉(zhuǎn)換
數(shù)據(jù)類(lèi)型既然有顯示的轉(zhuǎn)換,就有隱式轉(zhuǎn)換,而數(shù)據(jù)的隱式轉(zhuǎn)化主要是發(fā)生在JS中的運(yùn)算符操作和流程控制語(yǔ)句中。
// 1. 不同類(lèi)型的數(shù)據(jù)互相運(yùn)算
123 + 'abc' // "123abc"
// 2. 對(duì)非布爾值類(lèi)型的數(shù)據(jù)求布爾值
if ('abc') {
console.log('hello')
} // "hello"
// 3. 對(duì)非數(shù)值類(lèi)型的數(shù)據(jù)使用一元運(yùn)算符(即“+”和“-”)
+ {foo: 'bar'} // NaN
- [1, 2, 3] // NaN
這其中有兩個(gè)隱式轉(zhuǎn)化需要特別注意:”==“ 和 ”+“
“ + “號(hào)有兩種用途:一是作為加法運(yùn)算符,二是作為連接運(yùn)算符
// 當(dāng)其中一個(gè)是字符串,不管另一個(gè)是什么,都會(huì)轉(zhuǎn)換為字符串
"1" + "2" // "12"
"1" + 2 // "12"
"1" + true // "1true"
// 兩邊是數(shù)值或者布爾值(false轉(zhuǎn)換為0,true轉(zhuǎn)換為1),均相加
true + 1 // 2
ture + true // 2
ture + false // 0
1 + 2 // 3
還有一種情況是:
其中一邊或者兩都存在對(duì)象,則先調(diào)用該對(duì)象的valueOf方法。如果返回結(jié)果為原始類(lèi)型的值,則運(yùn)用上面兩條規(guī)則;否則繼續(xù)調(diào)用該對(duì)象的toString方法,對(duì)其返回值運(yùn)用上面兩條規(guī)則
1 + {} // 1[object Object]
1 + [] // 1 注意:這里空數(shù)組最終返回空字符串
1 + [1,2] // 11,2
function a() {
return 2;
}
1 + a // 1function a() {return 2}
1 + a() // 3
再來(lái)看” == “:
- 雙等號(hào)兩邊是否有NaN,如果有,一律返回false
- 兩邊是否存在布爾值,有則將布爾值轉(zhuǎn)換為數(shù)字(false是0,true是1)
- 一邊存在字符串時(shí):對(duì)方是對(duì)象,對(duì)象使用toString() 或者 valueOf() 轉(zhuǎn)換
- 對(duì)方是數(shù)字,字符串轉(zhuǎn)換為數(shù)字
- 對(duì)方是字符串,直接比較
- 其他均返回false
- 一邊是數(shù)字,對(duì)方是對(duì)象,對(duì)象使用toString() 或者valueOf() 比較,其他均返回false
- null和undefined比較,返回true
還要注意的是:
并不是對(duì)象轉(zhuǎn)換為字符串就是只調(diào)用 toString(),數(shù)值就只調(diào)用 valueOf()。
大多數(shù)對(duì)象(Date對(duì)象就是例外)的轉(zhuǎn)換會(huì)先調(diào)用valueOf()方法,再調(diào)用toString()方法
參考資料:
《JavaScript 高級(jí)程序設(shè)計(jì)》(第三版)
http://javascript.ruanyifeng.com/grammar/conversion.html#toc2
http://www.css88.com/archives/5199
http://www.haorooms.com/post/js_yinxingleixing