原生JS大揭祕—揭開數據類型轉換的面紗

在JS中數據類型轉換有兩種

相關資料參閱

官方ecma-5規範
阮一峯老師類型轉換
規範對相等==定義javascript

  1. 強制類型轉換
    Number() Number函數將字符串轉爲數值,要比parseInt函數嚴格不少,只要有一個字符是非數字(空格、+、-除外),那麼就會被轉爲NaN。

clipboard.png

String() 能夠將其餘類型轉成字符串
Boolean() 函數能夠將任意類型的值轉爲布爾值。html

  1. 隱式類型轉換
    https://www.jianshu.com/p/b07...
    https://www.jianshu.com/p/b16...

哪些狀況下會發生隱式類型轉換?

  1. 不一樣類型的數據互相運算
  2. 對非布爾值類型的數據求布爾值
  3. 對非數值類型的使用一元運算符(即"+""-")

重點說明: 操做符"+"是一個比較難搞、比較另類、比較奇葩的東西,"+"有兩種使用含義java

  1. 有字符串時,表示字符串拼接
  2. 無字符串時,表示算術加法

簡單的來講就是看"+"的兩端是否有任一個是字符串,有爲"字符串拼接",不然爲"算術加法"數組

隱式類型轉換原則

  1. 都是數字,直接運算
  2. 都是字符串,使用字符對應的ASCII值運算
  3. 有一個是boolean值,將boolean值轉成數字,true->1或false->0
  4. 有一個是數字,將另外一個轉成數字
  5. 只有一個是對象,則先將對象轉成原始值,在執行操做
  • 轉換過程當中若是有NaN出現,則結果是NaN或false

重點說明:null、undefined進行"=="比較時不進行類型轉換(可是ECMA規範中定義null==undefined // true ),其餘運算操做時會轉換。
"=="比較時,只有三種狀況爲true:
一、null==null
二、null==undefined
三、undefined==undefined
除以上三種狀況外其餘都不相等,返回false瀏覽器

說到NaN,隨便講一下全局函數isNaN(),咱們都知道這個函數判斷不許確,爲何呢?什麼緣由形成的呢?其實isNaN()方法只執行前,會對變量進行隱式類型轉換好比isNaN({}),返回true
首先進行隱式類型轉換,將{}=>Number,最終獲得NaN,因此isNaN({})獲得true函數

引用類型轉成原始類型分析

在JS內部定義了4個抽象操做(只能供JS內部使用,咱們用戶沒法操做)es5

  • ToPrimitive(obj, [PreferredType])
    obj:待轉換的對象
    PreferredType:待轉成的目標類型(只接受Number、String兩種類型,默認是空),若是obj是Datesymbol,則PreferredType=String,其他的狀況下PreferredType=Number

    若是PreferredType=Number,引用類型轉化爲數字
    一、調用valueOf(),若是返回原始值,則結束,若是返回非原始值,則執行第2步
    二、調用toString(),若是返回原始值,則結束,若是返回非原始值,則報錯spa

    若是PreferredType=String,引用類型轉換爲字符串
    一、調用toString(),若是返回原始值,則結束,若是返回非原始值,則執行第2步
    二、調用valueOf(),若是返回原始值,則結束,若是返回非原始值,則報錯code

    引用類型轉換爲布爾類型,始終返回truehtm

  • ToNumber(arguments)
  • ToString(arguments)
  • ToBoolean(arguments)

在執行隱式類型轉換時,會自動調用這四個內部方法
原始值之間相互轉換:ToNumber()、ToString()、ToBoolean()
引用值到原始值轉換: ToPrimitive()
在執行顯示類型轉換時,如Number()、String()、Boolean()時,內部仍是調用ToNumber()、ToString()、ToBoolean(),若是待轉換的是引用類型,則先執行ToPrimitive(),獲得原始值,再執行ToNumber()、ToString()、ToBoolean()

這裏特別說明:把 引用值原始值的過程當中JS內部在調用ToPrimitive()方法時,分爲兩種狀況
一、 明確指定目標轉換類型:按照指定類型去調用toString()/valueOf()方法
二、 沒有指定目標轉換類型:按照obj是不是 Date類型,去調用toString()/valueOf()方法

圖片描述

不一樣類型的對象調用toString()返回值不一樣:

  • {} => "[object Object]"
  • [] => ""
  • [1,2,3] => "1,2,3"
  • function(){} => "function(){}"
  • Date => "Mon Feb 12 2018 15:44:57 GMT+0800 (中國標準時間)"
  • RegExp => "/d/"正則字面量的字符串

不一樣類型的對象調用valueOf()返回值不一樣

  • Date類型 => 1518421497815 返回自1970年1月1日至如今的時間戳毫秒數
  • 其餘的類型 => 一概返回對象自身

JS數據類型之原始值與引用值的轉換關係圖解

clipboard.png

重點說明: 經過new Number()/new String()/new Boolean()獲得的是對象(不管傳入什麼參數),該對象有一個屬性[[PrimitiveValue]]`,此屬性保存着該對象對應的原始值。

clipboard.png

對於包裝對象而來,轉換成原始值時,有點特殊(不一樣於{}[]這種類型的對象),

  • valueOf(): 獲取[[PrimitiveValue]]屬性的值
  • toString(): 獲取[[PrimitiveValue]]屬性值的字符串形式

JS中數據轉換圖表

原始類型 目標類型(Number) 目標類型(String) 目標類型(Boolean) 目標類型(Object)
undefined NaN "undefined" false throw TypeError
null 0 "null" false throw TypeError
true 1 "true" true new Boolean(true)
false 0 "false" false new Boolean(true)
0 0 "0" false new Number(0)
-0 -0 "-0" false new Number(-0)
NaN NaN "NaN " false new Number(NaN)
Infinity Infinity "Infinity " true new Number(Infinity )
Infinity -Infinity "-Infinity " true new Number(-Infinity )
"7" 7 "7" true new String("7")
"" 0 "" 當且僅當是空字符串(即長度爲0)時,才返回false,其餘返回true,也就是" "爲true new String("")
"7M" NaN "7M" true new String("7M")
"M" NaN "M" true new String("M")
[] 0 "" true []
['7'] 7 "7" true []
{} 先ToPrimitive,再執行以上規則 先ToPrimitive,再執行以上規則 true {}
function(){} NaN true true function(){}

https://www.jianshu.com/p/0af...
提示1:只有空字符串("")、null、undefined、+0、-0 和 NaN 轉爲布爾型是 false,其餘的都是 true。
提示2:空數組、空對象轉換爲布爾型也是 true。
提示3:null 和 undefined 轉換爲數字是表現不一,分別爲0和NaN。

非數值型轉成數值型

非數值 -> 數值的方法有三種

  • Number()
  • parseInt()
  • parseFloat()

parseInt解刨

------------------------------------------------------------------------
 描述:是一個內置的函數,
 做用:能夠把一個字符串轉成整形,parseInt的返回值只有兩種狀況,a、十進制整數 b、NaN
 有兩個參數
   a、第一個參數表示待轉換的字符串(必須是字符串,若是不是字符串,則會發生隱式類型轉換
      而後對轉換後的字符串進行截取
   )

   b、第二個參數表示待轉換的字符串的進制(默認是10進制)
      該值的範圍介於[2,36],若是進制不在此範圍內的,一概返回NaN

      注意:基數若是不是數值,則發生隱式類型轉換,若是基數是NaN,則默認基數是10

   特別注意,這裏的默認進制10,是有條件的
   條件1,必須沒有明確指定進制數
   條件2,待轉換的字符串,不是以0或0x打頭的

   在字符串以"0"爲開始時舊的瀏覽器默認使用八進制基數。ECMAScript 5,默認的是十進制的基數。
   若是沒有明確指定進度,對於"0」打頭的字符串在「ES5以前」認爲是8進制
                     對於"0」打頭的字符串在」ES5以後「認爲是10進制

   若是有明確指定數的進制,則以指定的進度爲準

   var n=parseInt("11",2) //表示字符串"11"是2進制的數
   var n=parseInt("11",8) //表示字符串"11"是8進制的數
   var n=parseInt("11") //表示字符串"11"是10進制的數

   //注意了,radix是0、10均表示10進制的數,省略的時候進制多是八、十、16
   var n=parseInt("11",0) //表示字符串"11"是10進制的數
   var n=parseInt("11",NaN) //表示字符串"11"是10進制的數
   var n=parseInt("11",10) //表示字符串"11"是10進制的數


   使用方法總結:
   一、看參數1是不是字符串,若是不是則先轉成字符串(若是是非字符串類型,會發生隱式類型轉換)
   二、先肯定進制
   三、根據進制截取最終的字符串,若是最終是空字符串,則返回NaN
     (截取的規則是這樣的,從字符串的首位(若是是0的8進制數,則從0以後開始截取,有點特殊;若是是0x的16進制數,則從0x以後開始截取,有點特殊)
     (若是是空格、+會忽略哦,若是是-則會輸出)開始,依次向後截取,直到「非數字」或者「非指定進制範圍內」的字符截止)
   四、轉成10進制

   var num = parseInt(321, 0) //321
   var num = parseInt(321, NaN) //321
   var num = parseInt(321, 2) //NaN
   var num = parseInt("210", 3)//210
   var num = parseInt("329", 6)//20
   var num = parseInt("012", 0)//12
   var num = parseInt("0x12")//18
   var num = parseInt(parseInt,16)//15 這裏爲何是15呢?由於parseInt是一個函數,其實這裏的值是"function(){}"
   var num = parseInt(alert,16)//15
   var num = parseInt(console.log,16)//15
   var num = parseInt(0.000005)//0,直接使用「字面量」表示
   var num = parseInt(0.0000005)//5,這裏返回5是由於,小數位後面長度長多6位時,採用科學基數法表示,即」5e-7「

  =====================================================================
  對於數值型而言,小數位前長度大於21或小數位後長度大於6時,均使用科學計數法表示
  =====================================================================



  執行過程分析:(第一個參數命名爲參數1,第二個參數命名爲參數2)
  -----------------------------------------------------
  一、查看參數1是不是字符串,若是不是,則會發生隱式類型轉換
  二、肯定基數(進制)
       a、有明確指定基數,則以指定的基數爲準
       b、沒有明確指定基數,則以參數1進行判斷來肯定基數,
          首先,參數1字符串是以「0」打頭,則es5之前的版本中,基數爲8,es5以後的版本中,基數爲10
          其次,參數1字符串是以「0x"打頭,則基數是16,
          最後,其餘狀況,基數是10
  三、以肯定的基數來對參數1字符串進行有效性截取(非數字或基數範圍外的均視爲非法字符)
  四、若是截取的字符串是空字符串,「」則返回NaN
     若是是非空有效的字符串,則按照進制規則轉換成10進制的數


     0 1 2 3 4 5 6 7 8 9  A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z
     0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35

[0/0] == NaN
Infinity/Infinity == NaN
0/NaN==NaN
NaN/0==NaN
0/Infinity == 0
Infinity/0 == Infinity

關於在JS中「{}」的使用特別說明

  • 表示代碼塊
  • 表示一個JS對象

經典特殊數據類型轉換小結

clipboard.png

相關文章
相關標籤/搜索