🔥《ChatGPT 指令大全與創新應用》新書上架!👉 立即購買

JavaScript 有哪些資料型別 (data types)? 該怎麼辨別一個變數的資料型別?

如同絕大多數的程式語言,JavaScript 有其內建的資料型別。其中又有分原生值 (primitive values) 以及物件 (objects)。你知道在 JavaScript 當中有哪些是原生值? 哪些是物件? 又可以透過什麼樣的方法來辨別某個變數是什麼型別呢? 讓我們一起來看看這題面試常出現的基礎題吧!

JavaScript 的原生值 (primitive values)

截至目前,JavaScript 的資料型別中,有七個原生值。這七個原生值以外的,全都是屬於物件。

原生值是不可變的 (immutable),意思是我們不能改變那個值本身。舉例來說字串 (string) 是其中一個 JavaScript 原生值,我們不能去改變 'Hi' 這一個字串 (但在其他程式語言,字串有可能是可變的,例如在 C 就是可變的)。我們僅可以把某個變數,賦予另一個字串,例如:

let greeting = 'Hi';
greeting = 'Hello'; // 賦予另一個值,但上面的 'Hi' 本身沒變動

JavaScript 的型別中的七個原生值包含

String (字串)

字串是最常見的原生值之一。如前面提到,在 JavaScript 當中字串本身是不可變的。當我們用 substring() 來擷取字串,或用 concat() 來把兩個字串合為一,這些都是會回傳另一個字串,而非改變原本的字串。

Boolean (布林值)

truefalse 兩個值的布林值,也是 JavaScript 的原生值。

Number

JavaScript 與一些語言不同,沒有分整數與浮點數,而是都用 number 這個原生值。不論整數或浮點數,都是 number 這個型別。在 JavaScript 當中,+Infinity-Infinity, 與  NaN  都是 number 這個型別,所以我們用 typeof 來檢查的話,會得到 number

console.log(typeof NaN); // number

number 在 JavaScript 是雙精度浮點數,所以精確度是介於 -(2^53 − 1)2^53 − 1 之間。在這個範圍之外,就會有精準度的問題,這時候要用另一個原生值 BigInt

BigInt

上面提到在 JavaScript 的整數與浮點數,都是用 number 這個型別,這其實只說了一半。因為 JavaScript 的 number 精準度有其限制,雖然多數情況很夠用 (2^53 - 1 會是 9007199254740991,我們很少用到比這大的數)。但有些時候會需要更往下的精準度。這時就可以用 BigInt 數值的型別。

BigInt 可以讓我們任意選擇其精準度,就可以避免一些 number 會遇到的問題。它跟 number 一樣可以用 +*-**, 與  % 等運算子,不過要注意不可以拿 BigIntnumber 型別的值交互使用,這會出現 TypeError

Undefined

undefined 是一個型別,它本身也是一個值。假如某個變數還沒被宣告,我們就先使用,在 JavaScript 會出現索引錯誤 ReferenceError (如果是用 letconst 來宣告該變數)。但如果是宣告了,但沒有賦予某個值,這時因為對 JavaScript 來說,它不知道該變數的值是什麼,所以會印出 undefined

// 還沒宣告就使用,會有 `ReferenceError`
console.log(greeting); // Uncaught ReferenceError: greeting is not defined
let greeting;
// 宣告了但還沒賦值,會是 `undefined`
let greeting;
console.log(greeting); // undefined

Null

null 是很容易跟 undefined 搞混的原生值。undefined 是因為某變數還沒有賦值,所以對 JavaScript 來說,它不知道該變數的值是什麼,所以要讀取該變數時,會是 undefined。不過 null 則是我們賦予某個變數 null 這一個值。

Symbol

最後一個 JavaScript 原生值是 Symbol,它是一個獨特 (unique) 值,多半會搭配物件一起使用,作為物件的鍵 (key)。

const sym = Symbol('ExplainThis');
const obj = { [sym]: 'Interview Preps for Software Engineers' };
obj[sym]; // Interview Preps for Software Engineers

JavaScript 的物件 (objects)

除了上述的七個原生值以外的存在,在 JavaScript 當中都是物件。在 JavaScript 有一個梗是

Objects, Arrays, Functions, Objects 當中,Objects 好像被重複提了兩次。喔不,其實是四次。

會說 Objects 被提了四次說因為在 JavaScript 當中,Array (陣列) 與 Function (函式),都是物件。

如何辨別一個變數的資料型別?

要辨別一個變數的資料型別,最常見的方式是透過 typeof 這個方法。舉例來說 typeof 判斷字串。

let greeting = 'hi';
console.log(typeof greeting); // 'string'

不過在 JavaScript 當中,有幾個小例外,其中一個是 null 。如果用 typeof 判斷 null 的資料型別,會得到 object

console.log(typeof null); // object

這是一個 JavaScript 的歷史遺跡,但因為要改掉這個 bug 的成本太高,所以到目前為止還是有這個錯誤。

不論如何, null 的資料型別應該是 null 而不是 object。

另一點要注意的是,typeof 判斷陣列時,會回傳 object; 但判斷函式時,會回傳 function

console.log(typeof []); // object
console.log(typeof function () {}); // function

補充 typeof 結果的表格,來源參考 ECMAScript® 2015 Language Specification

Type of valResult
Undefined"undefined"
Null"object"
Boolean"boolean"
Number"number"
String"string"
Object (native and does not implement [[Call]])"object"
Object (native or host and does implement [[Call]])"function"
Object (host and does not implement [[Call]])Implementation-defined except may not be "undefined", "boolean", "number", or "string".

我們該如何辨別某個變數是物件,還是陣列呢?

Array.isArray() 是可以協助我們的。如果是陣列,會回傳 true;但若是一般物件,則會回傳 false。舉例來說:

Array.isArray([1, 2, 3]); // true
Array.isArray({ foo: 123 }); // false

我們也可以透過 Object.prototype.toString() 的方法幫助我們辨別陣列、函式與一般物件。

const arr = [1, 2, 3];
const fn = () => {
  return 123;
};
const obj = { foo: 123 };

console.log(Object.prototype.toString.call(arr)); // [object Array]
console.log(Object.prototype.toString.call(fn)); // [object Function]
console.log(Object.prototype.toString.call(obj)); // [object Object]
© 2023 explainthis.io
酉是數據科技股份有限公司