將寫作當(dāng)成興趣,并一直進(jìn)行下去。曾經(jīng)這是個(gè)小小的奢望,現(xiàn)在已經(jīng)在逐步的實(shí)現(xiàn)中。
長(zhǎng)話短說(shuō),既然是技術(shù)文,就不發(fā)這么多感慨了,接下來(lái),一起進(jìn)入今天的正題吧。
今天給大家分享的是 JavaScript中的隱式類型轉(zhuǎn)換問(wèn)題。相信很多的小伙伴都曾被它困擾過(guò),不論是開發(fā)中還是面試過(guò)程中。期望今天的分享能給你帶來(lái)不一樣的理解。也能讓你之后不再為此煩惱。
1. 基本數(shù)據(jù)類型
我們都知道,在 javascript 中一共有 7 中數(shù)據(jù)類型。分別是 Object, Null, Undefined, String, Number, Boolean, Symbol。這些東西我們?cè)谄綍r(shí)的開發(fā)過(guò)程中每天無(wú)時(shí)無(wú)刻不在接觸,這里我們不多贅述。
2. 強(qiáng)制類型轉(zhuǎn)換
平時(shí)的使用過(guò)程中,我們會(huì)遇到很多數(shù)據(jù)類型不一致的問(wèn)題,同樣,強(qiáng)制將不同的數(shù)據(jù)類型轉(zhuǎn)換為相同的數(shù)據(jù)類型也是很正常的操作;接下來(lái),我們看看都有什么樣的強(qiáng)制轉(zhuǎn)換方法:
2.1 字符串 -> 數(shù)字
1. parseInt
parseInt('123') // 123
parseInt('123abc') // 123
parseInt('12.3abc') // 12
parseInt('abc123') // NaN
解釋:
此方法只轉(zhuǎn)換 以數(shù)字開頭的,直到不是數(shù)字,然后轉(zhuǎn)換結(jié)束,如果字符串不是以數(shù)字開頭,則轉(zhuǎn)換為 NaN
2. parseFloat
parseFloat('123') // 123
parseFloat('12.3abc') // 12.3
parseFloat('1.2.3abc') // 1.2
parseFloat('abc1.23') // NaN
解釋:
規(guī)則同 parseInt ,只是注意小數(shù)點(diǎn)的轉(zhuǎn)換,只能轉(zhuǎn)換一個(gè)小數(shù)點(diǎn),如果是多個(gè)小數(shù)點(diǎn),則只保留一個(gè)。
3. Number
Number('123') // 123
Number('12.3abc') // NaN
Number('1.2.3abc') // NaN
Number('abc1.23') // NaN
解釋:
此方法只轉(zhuǎn)換 全數(shù)字 的字符串,如果字符串不是全數(shù)字。如'12.3abc','1.2.3abc','abc1.23'………… 的情況,統(tǒng)一轉(zhuǎn)換為 NaN
4. 位運(yùn)算
位運(yùn)算的使用在前端是特別少的,以至于很多前端人員不清楚具體使用。下面我們來(lái)看看,如何使用位運(yùn)算將字符串轉(zhuǎn)換為數(shù)字
主要有以下幾種操作方式可做轉(zhuǎn)換
-
~非 -
<<左移 -
>>右移
對(duì)于位運(yùn)算的實(shí)際運(yùn)算方式我們暫不做描述,本次只看如何使用它們將字符串轉(zhuǎn)為數(shù)字
~~'123' // 123 (這里是兩個(gè) ~~ 波浪線)
'123' << 0 // 123
'123' >> 0 // 123
解釋:
使用方法跟 Number 相同。都是只能轉(zhuǎn)換全數(shù)字的字符串。不為全數(shù)字的字符串,~轉(zhuǎn)換為 NaN ,另外兩種轉(zhuǎn)換為 0
2.2 數(shù)字 -> 字符串
1. 使用 + 運(yùn)算符。
'' + 123 // '123'
2. 使用 toString 方法
let num = 123
num.toString() // ‘123’
3. 使用 String 方法
let num = 123
String(num) // '123'
2.3 轉(zhuǎn)換為布爾值
1. !! 方法。(雙重否定即為肯定。使用雙重非可以得到原始值轉(zhuǎn)換的布爾值)
let num = 123
!!num // true
let str = '123'
!!str // true
2. Boolean 方法
let num = 123
let str = '123'
Boolean(123) // true
Boolean('123') // true
注意:
JavaScript 中為 false 的情況:
-
'',""空字符串 -
0數(shù)字0 undefinednullNaNfalse
3. 隱式類型轉(zhuǎn)換
3.1 可觸發(fā)隱式類型轉(zhuǎn)換的操作
- 四則運(yùn)算
+, -, *, / - 比較
> < >= <= ==。- 注意:
===是不會(huì)觸發(fā)隱式類型轉(zhuǎn)換的。
- 注意:
- 判斷
if, while
3.2 toString 和 valueOf 說(shuō)明
此兩種方法是將復(fù)雜數(shù)據(jù)類型轉(zhuǎn)換為原始值輸出。
1. 調(diào)用 valueOf 方法后
-
String, Number, Boolean返回的分別是 字符串值,數(shù)字值,布爾值。 -
Object, Array, Function返回的是自身 -
Date返回的是從開始到現(xiàn)在的毫秒值
2. 調(diào)用 toString 方法后
-
String, Number, Boolean返回的本別是字符串類型的值 -
Object返回的是[object Object] -
Array返回的是 空字符串。因?yàn)樵?Array中重寫了這個(gè)方法 -
function返回的是函數(shù)本身的字符串 -
Date返回的是時(shí)間,并非毫秒數(shù)
注意:
在獲取原始值(toPrimitive)時(shí),會(huì)先調(diào)用 valueOf 方法,如果返回的不是原始值(也就是說(shuō)返回的不是基本數(shù)據(jù)類型),則會(huì)繼續(xù)調(diào)用 toString 方法。如果還不是原始值。則會(huì)報(bào)錯(cuò)。
3.3 具體實(shí)例解析
請(qǐng)?jiān)诓榭唇馕鲋皣L試解答下方問(wèn)題
// 數(shù)組
[] == ![] // 1
[] == [] // 2
[] == false // 3
[] == true // 4
[1] == 1 // 5
[] == 0 // 6
[12] < [13] // 7
// 對(duì)象
{} == {} // 8
{} == !{} // 9
{} != {} // 10
// 結(jié)合版
[] + {} // 11
{} + [] // 12
{} + {} // 13
[] + [] // 14
{} + 1 // 15
1 + {} // 16
答案來(lái)咯,準(zhǔn)備好了沒(méi)
1. [] == ![] 執(zhí)行步驟
// 將原題中的 ![] 轉(zhuǎn)換為原始值 --> ![] 為false
[] == false
// 將 [] 轉(zhuǎn)換為原始值 [].valueOf() 返回自身,繼續(xù)調(diào)用 toString 返回 空字符串
'' == false
// 將空字符串轉(zhuǎn)換為 布爾值,空字符串為false
false == false
// 得到結(jié)果為 [] == ![] --> true
2. [] == []
比較的是地址,兩個(gè)數(shù)組的地址不相同。結(jié)果為false
3. [] == false
解答步驟同第一題[] == ![]
4. [] == true
解答步驟同第一題[] == ![]
5. [1] == 1
// 將 [1] 獲取原始值, 調(diào)用 valueOf 返回自身,繼續(xù)調(diào)用 toString 返回 '1'
1 == 1
// 得到結(jié)果 [1] == 1 --> true
6. [] == 0
// 將 [] 獲取原始值, 調(diào)用 valueOf 返回自身,繼續(xù)調(diào)用 toString 返回 ‘’
‘’ == 0
// 將空字符串轉(zhuǎn)換為數(shù)字 '' --> 0
0 == 0
// 得到結(jié)果 [] == 0 --> true
7. [12] < [13]
// 將左右都轉(zhuǎn)換為原始值
'12' < '13'
// 得到結(jié)果 true
8. {} == {}
同 [] == []
9. {} == !{}
同 [] == ![] 不同的是,這里的 {} 轉(zhuǎn)化為字符串之后為[object Object] 。 所以結(jié)果與 [] == ![] 相反
10. {} !== {}
同 {} == {} 反結(jié)果
11. [] + {}
// 將左右同時(shí)獲取原始值。
'' + '[object Object]' = '[object Object]'
12. {} + []
如果右邊的值不值一個(gè)字典格式,則會(huì)將大括號(hào)當(dāng)成一個(gè)空塊兒處理。也就是說(shuō)此時(shí)的表達(dá)式可以被轉(zhuǎn)換成如下表達(dá)式+ [],然后將 [] 先轉(zhuǎn)為空串,然后轉(zhuǎn)換為數(shù)字,得到數(shù)字0 。
所以: {} + [] == 0
13. {} + {}
左右兩邊都做對(duì)象處理,獲取原始值
'[object Object]' + '[object Object]' = '[object Object][object Object]'
14. [] + []
獲取左右的原始值,都轉(zhuǎn)換為了空字符串。然后做字符串拼接
'' + '' = ''
15. {} + 1
同 {} + [] ,可變形為 + 1
16. 1 + {}
將右方的 {} 獲取原始值,得到 '[object Object]' ,原式可變形為
1 + '[object Object]' = '1[object Object]'
4. 補(bǔ)充點(diǎn)
-
NaN與任何值都不相等,包括它本身(這得多很,自己跟自己都不相等) - 有
undefined參與的任意一個(gè)四則運(yùn)算,結(jié)果都為NaN - 布爾值
true轉(zhuǎn)數(shù)字時(shí),轉(zhuǎn)為1;false轉(zhuǎn)為數(shù)字時(shí)為0 - 字符串之間比較大小,實(shí)際比較的是字符編碼。如:
a > A = 97 > 65 = true
好了,今天的文章就分享到這兒咯,并沒(méi)有寫太多的概念,只是讓大家來(lái)多看下實(shí)際運(yùn)行的結(jié)果。一通則百通,知曉了實(shí)際運(yùn)行的過(guò)程,再遇到相似的問(wèn)題就游刃有余了。