JavaScript 是動態型別的 (Dynamically-typed) 語言
在 JavaScript 中,變數沒有綁定特定的型別,而是由資料本身來決定變數的型別。以下程式碼是合法的 JavaScript 程式:
// x is a boolean.
let x = true;
assert(typeof x === "boolean", "x should be a boolean");
// x becomes a string.
x = "hello";
assert(typeof x === "string", "x should be a string");
// x becomes a number.
x = 123;
assert(typeof x === "number", "x should be a number");
// x becomes an object literal.
x = {};
assert(typeof x === "object", "x should be a object");
// x becomes a function object.
x = (a, b) => a + b;
assert(typeof x === "function", "x should be a function object");
// Home-made `assert`
function assert(cond, msg) {
if (!(cond)) {
throw msg;
}
}
在此例中,變數 x
的型別改變數次,但程式仍可正常運作。當然,在實務上,我們不會一直改變變數的資料型別。
JavaScript 的基礎型別 (Primitive Type)
基礎型別就是程式中基本的資料型態,非物件的型別,包括以下數種:
- 空值 (null)
- 未定義 (undefined)
- 布林 (boolean)
- 數字 (number)
- 字串 (string)
- (新) 符號 (symbol)
空值
ECMAScript 有兩種空值,分別為 null
和 undefined
,兩者的意義略為不同,null
代表有值,而該值為空,而 undefined
表示值尚未定義。一般來說,明確使用 null
表示空值比較好,因為使用 undefined
會誤以為是忘了定義值。
布林 (Boolean)
布林只有兩個值,包括 true
和 false
,表示邏輯上的真和假。我們較少直接寫出 true
或 false
,而會撰寫條件式來改變程式執行流程。除了 true
和 false
外,程式設計者也要知道何謂 truthy 和 falsy 值,簡單地說,就是會判定為真或假的值,以下為 falsy 值:
- undefined
- null
- false
- 0
NaN
''
(空字串)
除了少數 falsy 值外,其他都是 truthy 值。要注意的是,以下是 truthy 值:
{}
(空物件)[]
(空陣列)" "
(含空格的字串)
數字 (Number)
ECMAScript 只有一種數字型態,就是倍精度浮點數 (double-precision floating-point number)。如果只進行整數部分的運算,不會有什麼問題,但在進行浮點數運算時,就要注意微小的誤差所帶來的錯誤:
assert(0.1 + 0.2 - 0.3 === 0.0, "It should be equal"); // Failed!
// Home-made `assert`
function assert(cond, msg) {
if (!(cond)) {
throw msg;
}
}
這些誤差來自於電腦內部儲存浮點數的方式,在電腦內部,浮點數是以其近似值的方式來儲存,每次運算都會帶來一些微小的誤差,對此議題有興趣的讀者可以參考一些計算機概論相關的書籍。
字串 (String)
ECMAScript 的字串有三種:
- 單引號字串
- 雙引號字串
- (新) 字串樣板
在字串中,跳脫字元 (escaped character) 指的是無法用鍵盤直接輸入的特殊符號,像是換行 "\n"
、TAB 符號 "\t"
等。ECMAScript 中,不論是單引號字串或是雙引號字串皆能處理跳脫字元,這和其他語言略有不同,如下例:
console.log('123\t456');
console.log("123\t456");
那麼,為什麼要區分兩種字串呢?主要是為了跳脫單引號或雙引號本身,如下例:
console.log('Don\'t talk with me.');
console.log("Don't talk with me.");
在上例中,為了要在單引號字串中使用單引號,必需要額外地使用跳脫字元,但在雙引號字串中則不需要。大部分情形下,使用雙引號字串較佳,因為一般文字中使用雙引號的機會較少,如果字串中可能會用到雙引號,則改用單引號字串。
附帶一提,如果要跳脫跳脫字元本身,就使用兩個跳脫字元 "\\"
,如下例:
console.log('C:\\User\\Michelle>');
字串樣板是為了簡化字串安插所加入的新語法。在加入這個語法前,若要在字串中安插動態資料,得用一堆加號進行字串相接,不但難寫而且難看,這個語法大大簡化字串安插的程式碼。如下例:
// String concatenation (old school).
let t1 = "2 + 3 = " + (2 + 3) + "\n"
+ "2 * 3 = " + (2 * 3);
// String template.
let t2 = `2 + 3 = ${2 + 3}
2 * 3 = ${2 * 3}`;
// Check whether two strings are equal.
if (t1 !== t2 ) {
throw "It should be equal";
}
(新) Symbol (符號)
符號是 ECMAScript 6 新的語法,主要是用來建立獨一無二的值,如下例:
const RED = Symbol();
const BLUE = Symbol();
if (RED == BLUE) {
throw "It should not be equal";
}
由於 ECMAScript 沒有內建的列舉 (enum) 型別,符號也可用來替代列舉。
物件型別 (Object Type)
ECMAScript (JavaScript) 建立物件 (object) 的方法有三種:
{}
(物件實字)- 函式物件
- (新)
class
保留字
前兩種是原本的 JavaScript 語法,而 class
算是一種語法糖。我們會在後文中說明建立物件的方法。
JavaScript 沒有類別 (class) 的概念,因為 JavaScript 的物件系統是以原型 (prototype) 為基礎。
JavaScript 的內建物件
JavaScript 內建以下物件:
- Number (數字)
- String (字串)
- Boolean (布林)
- Array (陣列)
- Date (日期)
- RegExp (常規表示式)
- (新) Map 和 WeakMap
- (新) Set 和 WeakSet
從內建物件的名稱,就可以猜出來該物件的功能。我們將於後文中說明。