型別

型別轉換 在 JavaScript

2 個練習

關於 型別轉換

在 JavaScript 中,值可以有不同的型別。你可以透過明確的_型別轉換_來改變變數的型別。除此之外,當情境需要時,JavaScript 也會執行_型別強制轉換_(隱性型別轉換)。

型別轉換

JavaScript 不像許多其他語言那樣有轉型成(其他)型別的語法,但你可以改用一些內建的輔助工具。其中最值得注意的是,全域物件 Boolean、Number 和 String 可以當作函式使用,把值轉換成對應的型別。

轉換成布林值(真值/假值)

用 Boolean(value) 可以把任何值轉換成布林值。這是怎麼運作的呢?

有一組固定的值,也就是所謂的_假值_,會轉換成 false。最重要的是,false、0、空字串、null、undefined 和 NaN 都是假值。MDN 上關於「Falsy」的文章列出了完整的清單。

對於其他所有的值,Boolean 會回傳 true。這些值則稱為_真值_。

Boolean(-1);
// => true

Boolean(0);
// => false

Boolean(' ');
// => true

Boolean('');
// => false

請注意,根據上述規則,在 JavaScript 中 '0'、'false'、[] 和 {} 都是真值。

轉換成數字

你可以用 Number(value) 把值轉換成數字。字串開頭和結尾的空白會被忽略,空字串則會轉換成 0。如果你試著轉換非原始型別的值,或是不代表數字的字串,不會拋出錯誤。結果會是 NaN(非數字)。

Number('  -12.34  ');
// => -12.34

Number('1,2');
// => NaN

Number('1 2');
// => NaN

Number('');
// => 0

Number('10e3');
// => 10000

Number({ key: '123' });
// => NaN

下面可以看到 Number 對其他原始型別的值會回傳什麼。

Number(true);
// => 1

Number(false);
// => 0

Number(null);
// => 0

Number(undefined);
// => NaN

請注意,和上一個例子不同,不帶任何引數呼叫 Number() 時,定義上會回傳 0。

JavaScript 也提供了 parseInt 和 parseFloat 這兩個函式。它們對於哪些字串可以轉換成數字,採用比較寬鬆的規則。因此,為了避免出乎意料的結果,最好優先使用 Number 做為轉換函式。

parseInt('123a45');
// => 123

Number('123a45');
// => NaN

轉換成字串

用 String(value) 可以把值轉換成字串。對原始型別的值來說,結果就跟你想的一樣。

String(12.34);
// => '12.34'

String(false);
// => 'false'

String(null);
// => 'null'

String(undefined);
// => 'undefined'

對陣列來說,String 函式會對每個元素套用字串轉換,再用逗號把結果串接起來。你也可以自己套用 join 方法,例如自訂分隔符號。不過在這些情況下,null 和 undefined 會被轉換成空字串。

String([42, null, true, 'abc']);
// => '42,,true,abc'

對物件來說,String 預設會回傳一段沒什麼用的文字。

String({ key: 'value' });
// => '[object Object]'

你可以自訂轉換行為,例如提供一個 toString 方法。javascript.info 上的「Object to primitive conversion」一節說明了細節。

另一個常見的做法,是用 JSON 編碼 讓物件和陣列有更好的字串表示法。你可以用 JSON.stringify 轉換成字串,再用 JSON.parse 轉換回物件或陣列。

const obj = {
  name: 'Gilda Guerra',
  address: {
    city: 'Goiânia',
  },
};

JSON.stringify(obj);
// => '{"name":"Gilda Guerra","address":{"city":"Goiânia"}}'

型別強制轉換

在某些情境下,JavaScript 會在執行某個敘述之前,自動把值轉換成另一種資料型態。這種隱性轉換就叫做_型別強制轉換_。

布林情境

當值用在布林情境中時,JavaScript 會套用和 Boolean 函式相同的規則,隱性地轉換這個值。

  • 當 if 敘述 的條件不是布林值時,會套用強制轉換來判斷條件是否成立。三元運算子 ? 的第一個運算元也是如此。

    const num = 0;
    if (num) {
      // this block is NOT executed because 0 is falsy
    }
    
    const name = 'Jin';
    name ? 'name was provided' : 'no name provided';
    // => 'name was provided'
    
  • 邏輯 NOT 運算子 ! 的運算元,也會在套用 NOT 運算之前先被強制轉換成布林值。

    const name = '';
    !name;
    // => true
    

    這種行為的一個結果是,!!value 的效果和 Boolean(value) 相同。不過為了可讀性,你還是應該使用 Boolean。

  • JavaScript 也會對邏輯 AND(&&)和 OR(||)運算子的運算元套用強制轉換。但請記住,運算式的結果不一定是布林值。它會回傳其中一個原本的運算元(請參閱 MDN 上的邏輯運算子)。

    null || 'hello';
    // => 'hello'
    

字串情境

如果加法運算子 + 用在原始型別的值上,而其中一個運算元是字串,另一個運算元也會被強制轉換成字串。轉換邏輯和使用 String 函式時相同。之後,這兩個字串會被串接起來。

let name;
'hello ' + name;
// => 'hello undefined'

嵌入 模板字串 中的非字串值,也會發生同樣的隱性轉換。

const degrees = 23;
`It is ${degrees} °C`;
// => 'Is is 23 °C.';

數字情境

許多運算子會依照上面說明的 Number 函式邏輯,(在必要時)把運算元強制轉換成數字。

  • 算術運算子:+(如果沒有牽涉到字串)、-、*、/、%、**
  • 一元加號與一元負號運算子:+、-
  • 關係運算子(用於非字串的運算元):>、>=、<、<=
  • 位元運算子:|、&、^、~

關於這些運算子的更多細節,請參閱 MDN 的運算子清單。

當運算元有可能是字串時,最好一律用 Number 函式明確轉換,以避免出錯。

'1' + '2';
// => '12'
// addition operator in string context as explained above

Number('1') + Number('2');
// => 3

有時候你會看到有人用一元加號運算子把字串強制轉換成數字。這並不推薦,因為它比明確呼叫 Number 難懂得多。

const value = '42';
+value;
// => 42

Number(value);
// => 42

使用寬鬆相等與不相等運算子 ==/!= 時,也常常牽涉到隱性的數字轉換。不過,這些運算子的確切邏輯相當複雜(請參閱 MDN 上的寬鬆相等)。結果難以預測,有時甚至和你想的不一樣。請改用嚴格相等/不相等運算子 ===/!==,以避免這些隱性轉換。

透過 GitHub 編輯 連結會在新視窗或分頁中開啟

學習 型別轉換