Learning Objectives
- 說出 JavaScript 的七種原始型別,並用 typeof 判斷一個值的型別
- 分辨 undefined、null 與 NaN 的意思,知道怎麼正確檢查 NaN
- 用 parseInt、parseFloat、Number 把字串轉成數字,並預測它們的差別
- 用 toString、String 與字串連接把值轉成字串,說明 + 遇到字串時的行為
每個值都有型別
程式裡的每一個值都有型別(type),型別決定了這個值能做什麼:數字可以相乘,字串可以取出第幾個字。 JavaScript 的值分成兩大類:
| 類別 | 型別 | 例子 |
|---|---|---|
| 原始型別(primitive) | number 數字 |
42、3.14、NaN |
string 字串 |
'Hello'、"你好" |
|
boolean 布林值 |
true、false |
|
undefined |
宣告了但還沒給值 | |
null |
刻意表示「沒有值」 | |
bigint 大整數 |
123n |
|
symbol 符號 |
Symbol('id') |
|
| 物件(object) | 物件、陣列、函式、日期… | { name: 'Amy' }、[1, 2] |
typeof 值 會回傳一個字串,說明這個值的型別。有兩個地方要特別記住:
typeof null是"object":這是 JavaScript 早期留下的錯誤,為了相容舊網頁一直沒有修正。要檢查 null 請寫x === null。- 陣列的
typeof也是"object";要判斷是不是陣列用Array.isArray(x)。
七種原始型別與 typeof
先看第 2~8 行建立的七個變數在右邊框架裡的樣子,再看第 10~13 行印出的 typeof 結果。哪兩個結果和你想的不一樣?
Number:只有一種數字
JavaScript 不分整數和小數,1、1.0、1.1 都是 number,內部用 IEEE 754 的 64 位元浮點數儲存。
| 寫法 | 意思 | 值 |
|---|---|---|
255、3.14 |
十進位 | 255、3.14 |
0xff |
十六進位(0x 開頭) | 255 |
0b1010 |
二進位(0b 開頭) | 10 |
0o17 |
八進位(0o 開頭) | 15 |
123e5、123e-5 |
科學記號 | 12300000、0.00123 |
三個特別的數字值:Infinity(正無限大,例如 10 / 0)、-Infinity、NaN(Not a Number,不是有效的數字,例如 0 / 0、'abc' * 2)。
浮點數有兩個要注意的地方:
- 小數不一定能精確表示:
0.1 + 0.2得到0.30000000000000004。要顯示到小數第幾位用toFixed(位數)(回傳的是字串)。 - 整數只在
Number.MAX_SAFE_INTEGER(9007199254740991)以內是精確的,超過就可能失準;需要更大的整數時改用 BigInt。
舊程式碼裡可能看到 010 這種「0 開頭」的八進位寫法,在嚴格模式下是語法錯誤,請改用 0o10。
數字的寫法與特別的值
第 2~6 行用五種寫法建立數字,看右邊的框架:不管怎麼寫,存進去的都是一般的十進位數字。最後一行印出的數字,和程式裡寫的差了 1。
Boolean、undefined、null 與 NaN
- Boolean:只有
true、false兩個值,常用在if判斷要不要執行某段程式。 - undefined:「還沒有值」。宣告了沒給值、讀取物件不存在的屬性、函式沒有
return,得到的都是undefined。 - null:「刻意設成沒有值」,例如使用者清空了某個欄位。
null是程式設計者自己指定的。 - NaN:運算的結果不是有效的數字。它有一個怪特性:NaN 和任何值都不相等,連自己也不相等,
所以
x === NaN永遠是false。檢查 NaN 要用Number.isNaN(x)。
String 字串的寫法與方法在 j06 會詳細介紹。
undefined、null 與 NaN
看第 11 行:result 明明是 NaN,result === NaN 卻是 false。第 13 行比較 null 和 undefined:用 == 和 === 結果不同。
想一想:型別
下面的程式會印出什麼?
console.log(typeof null, typeof NaN);
要檢查變數 x 是不是 NaN,下列哪一個寫法正確?
下面的程式會印出什麼?
const user = { name: 'Amy' };
let age;
console.log(age, user.city);
轉換為 Number
從輸入框、網址、檔案讀進來的資料都是字串,要計算之前得先轉成數字。三種常用的方法:
| 方法 | 規則 | '12.5px' |
'' |
'abc' |
|---|---|---|---|---|
parseInt(字串, 進位) |
從頭讀,讀到不是數字的字元就停,只取整數部分 | 12 |
NaN |
NaN |
parseFloat(字串) |
從頭讀,可以讀小數點與科學記號 | 12.5 |
NaN |
NaN |
Number(值) |
整個值都要是合法的數字,否則 NaN;前後空白會忽略 |
NaN |
0 |
NaN |
parseInt的第二個參數是進位(2~36):parseInt('11', 2)是 3、parseInt('1f', 16)是 31。建議一律寫上10,意思最清楚。Number也可以轉布林值與 null:Number(true)是 1、Number(false)是 0、Number(null)是 0、Number(undefined)是NaN。- 在值前面加一個
+(例如+'42')效果和Number('42')相同,舊程式碼常看到。
怎麼選:要「整個字串都是數字才算數」(例如表單驗證)用 Number;要從 '12px' 這種字串取出開頭的數字用 parseInt/parseFloat。
parseInt、parseFloat 與 Number 的差別
投影片 LAB02 的延伸:同一類字串交給三個方法,結果常常不一樣。播放到最後,對照輸出的每一行。
轉換為 String
| 方法 | 說明 | 例子 |
|---|---|---|
數字.toString(進位) |
數字轉字串,可以指定 2~36 進位 | (15).toString(2) → '1111' |
String(值) |
任何值都能轉,包括 null、undefined |
String(null) → 'null' |
值 + '' |
和字串相加,另一邊會自動轉成字串 | 1 + '' → '1' |
`${值}` |
樣板字面值(j06 介紹) | `${7}` → '7' |
null.toString() 會出錯(null 沒有任何方法),String(null) 則可以安全地得到 'null'。
+ 的規則:兩邊都是數字就相加;只要有一邊是字串,另一邊就轉成字串再連接。
運算由左到右進行,所以 1 + 2 + '' 是 '3','' + 1 + 2 卻是 '12'。
toString、String 與字串連接
注意第 11~13 行:同樣是 a、b 和一個空字串,順序不同,結果就不同。
想一想:型別轉換
下面的程式會印出什麼?
console.log(parseInt('12px'), Number('12px'));
下面的程式會印出什麼?
console.log(Number(''), Number(null), Number(undefined));
下面的程式會印出什麼?
const n = 255;
console.log(n.toString(16) + 1);
下面的程式會印出什麼?
console.log('' + 3 + 4, 3 + 4 + '');
實作:把字串轉成數字再計算
從網頁表單讀到的值都是字串。單價 '120'、數量 '3'、運費 '60',直接計算會得到奇怪的結果。把它們轉成數字,算出正確的總價 420,並確認 total 的型別是 number。
重點精華回顧
- JavaScript 有七種原始型別:number、string、boolean、undefined、null、bigint、symbol;其他的都是物件。
typeof回傳型別名稱;注意typeof null是"object",陣列也是"object"。- 數字只有一種 number:可以寫成十六進位、二進位、科學記號;有
Infinity與NaN,小數有浮點誤差。 undefined是還沒有值、null是刻意設成沒有值;NaN 不等於任何值,要用Number.isNaN()檢查。- 轉數字:
parseInt、parseFloat從頭讀到不能讀為止;Number要整個值都合法。 - 轉字串:
toString(進位)、String()、和字串相加;+只要有一邊是字串就變成連接,而且由左到右計算。