1. 程式人生 > >JS型別轉換總結

JS型別轉換總結

前言

JS 令人頭疼的一點就是它屬於弱型別語言,一個變數儲存的值可以是字串、數值、布林值或者物件等,可以隨時變更。獲取一個變數,你不會知道其儲存的值是什麼型別的,所以很多時候都需要進行型別檢測。

除了手動變更型別之外,有些情況下,JS 內部也會自動進行型別轉換,以滿足部分操作符以及語句等的執行。

下面就是我對 JS 型別轉換的一些總結,其中大部分來自《JavaScript 高階程式設計》這本書。

1. Boolean 轉換

轉換情況

  • 呼叫 Boolean()
  • ifwhile 流程控制中,內部執行相應的 Boolean() 轉換
  • 邏輯運算子,主要是 !!!,內部執行 Boolean()
    轉換

轉換規則

資料型別 轉換為 true 的值 轉換為 false 的值
String 任何非空字串 空字串""
Number 任何非零數字值(包括無窮大) 0NaN
Object 任何物件 null
Undefined 不適用 undefined

也就是說,只有 0 / NaN / "" / null / undefined 才會轉換為 false,其餘都是 true

所以在 if 判斷中,直接寫變數有時候是不夠嚴謹的

if (!a){
  //=> 想要在 a 不存在或沒定義的時候執行
//=> 實際上儲存的值是 0 或者 '' 等也會執行 } //=> 應該使用 typeof if (typeof a == 'undefined') { //=> a 不存在或沒定義的時候執行 } //=> 或者使用全等 if (a === undefined) { //=> 使用 == 也不夠嚴謹,因為 null == undefined //=> 需要區分 null 或 undefined 的 情況較少 }

2. Number 轉換

轉換情況

  • 呼叫 Number()parseInt()parseFloat()
  • 其他情況都是使用 Number()
    的轉換機制
    • isNaN()
    • 一元加或減操作符,注意:這裡是一元的,如 s = + s,區別於加法和拼接
    • 遞增或遞減,以及加法(除了拼接)、減法、乘法、除法、求模等操作符
    • 關係操作符

轉換規則

Number()
- Boolean 值
- true => 1
- false => 0

  • null => 0

  • undefined => NaN

  • String 值

    • 只包含數字(包含正負號),將其轉換為十進位制數值,忽略前導零
    • 包含有效的浮點格式,將其轉換為對應的浮點數值,忽略前導零
    • 包含有效的十六進位制格式,將其轉換為相同大小的十進位制數值
    • 空字串 "",空格 ' ',換行符'\n',製表符'\t' => '0'
    • 包含其他格式的字串,則將其轉換為 NaN
  • Object 值

    • 呼叫物件的 toString() 方法,然後依照上面的規則轉換返回的字串
// [普通物件]
({}).toString() => '[object Object]' => NaN

// [陣列]
[12,23].toString() => '12, 23' => NaN
[12].toString() => '12' => 12
[].toString() => '' => 0

// [正則]
/^$/.toString() => '/^$/' => NaN

// [函式]
function a() {}
a.toString() => "function a(){}" => NaN

parseInt()
- 第一個引數必須是字串,如果不是則轉換為字串,使用 toString() 方法轉換為字串
- 忽略前面的空格,直至找到第一個非空字元
- 第一個非空字元不是數字字元或者負號,則返回 NaN
- 空字串返回 NaN
- 第一個是數字字元,會繼續解析下一個字元,直至遇到非數字字元,返回前面的數字字元
- 遇到非數字字元後,後面的字元都是無效的了
- 傳入第二個引數:轉換時使用的基數,即多少進位制,就可以解析二進位制、八進位制、十六進位制的字串。指定了第二個引數的,字串中甚至不用帶前面的字首,如 parseInt("AF", 16);//175
- 為了避免解析錯誤,任何情況下都應該明確指定基數,十進位制也不例外

parseFloat()
- 第一個引數必須是字串,如果不是則轉換為字串,使用 String() 方法
- 字串中第一個小數點有效,第二個無效
- 空字串返回 NaN
- 始終忽略前導零
- 只要遇到非浮點字元或者第二個小數點,後面的字串都無效
- 字串解析為整數,那麼返回整數

3. String 轉換

轉換情況

  • 基於 alert / confirm / prompt / document.write 等方法輸出內容
  • 呼叫 toString()String()
  • 加號操作符,有一個是字串時,內部呼叫 toString()
  • 物件轉換成 Number 型別時,內部呼叫 toString()

轉換規則

toString() 方法
- 返回相應值的字串表現
- 數值、布林值、物件和字串值都有一個 toString() 方法
- 字串的 toString() 方法返回字串的一個副本
- null => "null"
- undefined => "undefined"
- NaN => 'NaN'
- true => 'true'false => 'false'
- 普通物件只能返回 [object Object],不能返回字串形式
- 陣列 [] => ''[12, 23] => '12,23'
- 正則、日期等物件都返回其字串表現

String() 轉型函式,你可以認為 StringtoString 轉換機制是一樣的。

4. 特殊轉換

+ 號操作的特殊情況

// 雖然沒有看到字串,但是引用型別轉換為數字時,會先轉換為字串,這樣就變成了字串拼接
[12] + 10 //=> "1210"
({}) + 10 //=> '[object Object]10'

{} + 10 //=> 10
//=> 原因是 {} 會被解析為程式碼塊,最後只是操作了 +10 

{} + {} //=> '[object Object][object Object]'
//=> 非常特殊,不同瀏覽器解析有差異

({})+{} //=> '[object Object][object Object]'
{} + ({}) //=> NaN
//=> 一行中開頭的 {} 才會被解析為程式碼塊,所以用 () 包裹後可以避免被解析為程式碼塊,一行後面的 {} 不會被解析為程式碼塊,而是空物件。

== 進行比較時
物件 == 物件:地址相等才相等

{} == {} //=> false
[] == [] //=>false
{name: 'xxx'} == {name: 'xxx'} //=> false

var obj1 = {};
var obj2 = obj1;
obj1 == obj2 //=> true

物件 == 數字:把物件轉換為數字
物件 == 布林:都轉化為數字
字串 == 數字:把字串轉換為數字
字串 == 布林:都轉化為數字
布林 == 數字:把布林轉換為數字
物件 == 字串:把物件轉換為字串之後再比較

1==true //=> true
1==false //=> false
2==true //=> false,都轉化為數字

[]==false //=> true,都轉換為數字
[]==true //=> false,都轉換為數字
![]==false //=> true,先算 ![] 為 false,再比較
![]==true //=> false,先算 ![] 為 false,再比較
[]==![] //=> true,先算 ![] 為 false,然後都轉換為數字再比較