【JS基礎】類型轉換知多少

開胃菜

先說一個題外話,我在工做中遇到一個問題,須要比較 "08:00""09:00" 的大小,最後我找到三種方法:html

  • 在兩個字符串先後各拼接相同的年月日和秒,拼成完整的時間格式進行比較:
var head = "2016-01-01 "
var foot = ":00"

var time1 = head + "08:00" + foot //"2016-01-01 08:00:00"
var time2 = head + "09:00" + foot //"2016-01-01 09:00:00"

剩下的就不說了,比較兩個完整的日期仍是很容易的。數組

  • 把兩個字符串中的冒號去掉,轉換成數字進行比較:
function timeToNumber(time) {
    let [head,foot] = time.split(":")
    return Number(head+foot)
}

var time1 = timeToNumber("08:00") //800
var time2 = timeToNumber("09:00") //900
  • 直接比較

對,你沒有看錯,直接比較兩個字符串:函數

"08:00" > "09:00" //false

看到這裏估計有人就納悶了,很明顯第三種方法是更簡潔的,可是字符串比較,好像不多見,它比較的依據是什麼呢?post

其實,字符串比較大小,會從左到右依次取兩個字符串中的字符,兩兩比較他們charCodeAt()的結果,直到比較出大小就中止。好比:學習

var str1 = "a11"
var str2 = "a2"
// str1 和 str2 比較的時候,會先比較 str1[0] 和 str2[0],兩個都是 "a",比較下一個
// str1[1] 是"1",charCodeAt()是49,str2[1] 是"2",結果是50,因此 str1[1] < str2[1],對比結束
// 最終結果 str1 < str2

同理,在比較"08:00""09:00"的時候,先比較兩個"0",發現一致以後比較"8""9",因此"08:00" < "09:00"spa

這裏有一個問題就是,時間格式必須保持一致,位數不夠的記得補"0",拿"8:00""10:00"比較會發現結果有問題,必須拿"08:00""10:00"比較才能夠。code

這個問題就說到這裏,你們有其餘的方法能夠留言補充,給你們提供不一樣的思路。開胃菜結束,進入正題。htm

正題

做爲一個愛(記)學(不)習(清)的好(笨)孩子,經過字符串比較這件事,我意識到還有更多的非相同類型的比較,好比字符串和數字的比較,布爾和數組的比較(我瘋了麼我這麼用),另外還有加減乘除等其餘操做符。對象

我以爲有必要整理一下了。blog

我第一反應是這張圖:

真是迷人的笑容呢 :)

在比較以前,咱們須要先了解下各類數據類型轉化的結果有哪些。

轉數字

  • 字符串:

    • 空字符串是0
    • 字符串頭尾有空格會忽略
    • 空格在中間,或者字符串中含有非數字類型字符,轉換結果就是NaN
  • 布爾:true -> 1, false -> 0
  • undefined字: NaN
  • null: 0
  • 數組:

    • 空數組是0
    • 若是數組中有且只有一項是數字元素,轉換爲數字
    • 其餘狀況NaN
  • 對象:

    • 若是對象有valueOf()方法,就調用該方法。若是返回基本類型值,就將這個值轉化爲數字
    • 若是對象沒有valueOf()方法或者該方法返回的不是基本類型值,就會調用該對象的toString()方法。若是存在且返回值是基本類型值,就轉化爲數字
    • 不然就報錯
  • 函數:NaN

轉字符串

  • undefined -> "undefined"
  • null ->"null"
  • true -> "true" / false ->"false"
  • 數字:極小和極大的數字使用指數形式,通常的狀況你懂得
  • 對象:

    • 若是對象有toString()方法,就調用toString()方法。若是該方法返回基本類型值,就將這個值轉化爲字符串
    • 若是對象沒有toString()方法或者該方法返回的不是基本類型值,就會調用該對象的valueOf()方法。若是存在且返回值是基本類型值,就轉化爲字符串
    • 不然就報錯
    • 除非自行定義,不然toString()返回內部屬性[[Class]]的值,如"[object Object]"

轉布爾

  • 全部的假值(undefinednull+0-0NaN"")會被轉化爲 false,其餘都會被轉爲true
  • 因此,空對象、空數組都是true

轉對象

  • nullundefined轉對象直接拋異常
  • 基本類型經過調用String()Number()Boolean()構造函數,轉換爲他們各自的包裝對象

使用場景

知道了各類數據類型轉化的規則,那麼在不一樣的場景中,到底是怎麼使用的呢?

== 運算符

常見的誤區是:==檢查值是否相等,===檢查值和類型是否相等。

正確的解釋是:==容許在相等比較中進行強制類型轉換,而===不容許。

事實上,=====都會檢查操做數的類型,區別在於類型不一樣時它們的處理方式不一樣。

  1. 若是一個值是null,另外一個值是undefined,則相等
  2. 若是一個是字符串,另外一個值是數字,則把字符串轉換成數字,進行比較
  3. 若是任意值是true,則把true轉換成1再進行比較;若是任意值是false,則把false轉換成0再進行比較
  4. 若是一個是對象,另外一個是數值或字符串,把對象轉換成基礎類型的值再比較

    • 對象轉基礎類型時,優先調用valueOf(),再調用toString()
    • 例外的是DateDate 利用的是toString()轉換

經典題

[] == false // true
!![] // true

//緣由是 == 兩邊都轉爲數字進行比較,而不是 [] 轉爲布爾值與 false 比較

+ 運算符

+ 運算符能夠做爲一元運算符使用,此時的做用是將後邊跟着的數據轉爲數字

+true // 1
+[] // 0
+new Date() //獲取當前時間的Unix時間戳

在做爲二元運算符使用時,+運算符比- * /運算符要複雜一些,由於其餘的運算符都是處理數字的,而+運算符還能夠處理字符串拼接。

  • 兩邊若是有字符串,另外一邊會轉化爲字符串進行相加
  • 若是沒有字符串,兩邊都會轉化爲數字進行相加,對象也根據前面的方法轉化爲數字
  • 若是其中的一個操做數是對象,則將對象轉換成原始值,日期對象會經過 toString()方法進行轉換,其餘對象經過valueOf()方法進行轉換,可是大多數都是不具有可用的valueOf()方法,因此仍是會經過toString()方法執行轉換

簡單來講就是,若是+運算符的其中一個操做數是字符串(或者經過以上步驟能夠獲得字符串),那麼就執行字符串拼接,不然執行數字加法。

經典題

!+[]+[]+![] //"truefalse"

//首先第一個 + 左邊不是數值,因此它是一元運算符,將後邊跟着的 [] 轉化爲數字 0
//同時,最後一個 [] 左邊是 ! 運算符,將 [] 轉化爲布爾值並取反,爲 false
//轉化後的結果爲 !0 + [] + false
//!0 結果爲 true,[] 轉化爲 "",因此結果變爲 true + "" + false
//由於 第一個 + 右邊有字符串,因此變爲"true" + false
//最終結果爲 "truefalse"

條件判斷

如下條件判斷的語句,會發生隱式轉換爲布爾值的狀況:

  • if()語句中的條件判斷表達式
  • for(..; ..; ..)語句中的條件判斷表達式
  • while()do .. while()
  • ? : 中的條件判斷表達式
  • ||&&左邊的操做數

補充:valueOf()和toString()

經常使用內置對象調用toString()valueOf()的返回狀況

類型 toString valueOf
Object "[object 類型名]" 對象自己
String 字符串值 字符串值
Number 返回數值的字符串表示。還可返回以指定進製表示的字符串,默認10進制 數字值
Boolean "true" / "false" Boolean
Array 每一個元素轉換爲字符串,用英文逗號做爲分隔符進行拼接 數組自己
Date 日期的文本表示,格式爲Wed Jun 05 2019 18:22:32 GMT+0800 (中國標準時間) 返回時間戳,等同於調用getTime()
Function 函數的文本表示 函數自己
RegExp 正則的文本表示 正則自己

以上是本篇文章的內容,歡迎你們提出本身的想法,咱們一塊兒學習進步,與君共勉。

參考資料

相關文章
相關標籤/搜索