偷偷運(yùn)行的邏輯 - JavaScript隱式類型轉(zhuǎn)換

將寫作當(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
  • undefined
  • null
  • NaN
  • false

3. 隱式類型轉(zhuǎn)換

3.1 可觸發(fā)隱式類型轉(zhuǎn)換的操作

  • 四則運(yùn)算 +, -, *, /
  • 比較 > < >= <= ==。
    • 注意: === 是不會(huì)觸發(fā)隱式類型轉(zhuǎn)換的。
  • 判斷 if, while

3.2 toStringvalueOf 說(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)題就游刃有余了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容