跳至主要内容

JavaScript 的型別

JavaScript Types

Standard built-in objects

// Primitive
typeof 5; // number
typeof true; // boolean
typeof "Word"; // string
typeof undefined; // undefined
typeof null; // object
typeof Symbol("Just me"); // symbol

// Non-Primitive
typeof {}; // object
typeof []; // object
typeof function () {}; // function
  • Symbol 是 ES6 的新型別

  • array 與 function 都是 object

  • object 以外的型別都是 primitive type

  • primitive type 只會是一個值

    MDN 文件

Array.isArray()

利用 Array.isArray(引數) 可檢視引數是否為陣列

Array.isArray([]); // true
Array.isArray({}); // false

Pass By Value vs Pass By Reference

當宣告某變數並儲存另一變數的值時,傳址的優點是可以避免佔用太多儲存空間。

let a = 1;
let b = a;
b++;
console.log(a); // 1
console.log(b); // 2

let c = [1, 2, 3];
let d = c;
d.push(4);
console.log(c); // [ 1, 2, 3, 4 ]
console.log(d); // [ 1, 2, 3, 4 ]

若真的需要複製 array,可使用 concat( ) 或展開運算子複製 array。
若真的需要複製 object,可使用 Object.assign( ) 或展開運算子複製 object。

以下程式碼利用上述方法複製物件,而非使用傳址的特性,
因此在原始物件內容變更後,複製物件的值不會隨之更動。

let a = [1, 2, 3];
let b = [].concat(a);
a.push(4);
console.log(b); // [1, 2, 3]

let c = { a: 1, b: 2, c: 3 };
let d = Object.assign({}, c);
c.c = 333;
console.log(d); // { a: 1, b: 2, c: 3 }

let e = { a: 1, b: 2, c: 3 };
let f = { ...e };
e.c = 333;
console.log(f); // { a: 1, b: 2, c: 3 }

淺拷貝(shallow copy)深拷貝(deep copy)

物件裡的物件依然是傳址,利用展開運算子或 Object.assign() 淺拷貝物件後,
若修改原始物件內的物件,會影響到複製物件的值。
若要避免複製物件內的物件隨著原始物件變動,
需使用深拷貝。然而深拷貝需小心使用,否則會嚴重影響效能。

let a = { a: 1, b: 2, c: { key: "GG" } };
let b = { ...a };
let c = Object.assign({}, a);
let d = JSON.parse(JSON.stringify(a));

a.c.key = "QQ";

console.log(a); // { a: 1, b: 2, c: { key: 'QQ' } }
console.log(b); // { a: 1, b: 2, c: { key: 'QQ' } }
console.log(c); // { a: 1, b: 2, c: { key: 'QQ' } }
console.log(d); // { a: 1, b: 2, c: { key: 'GG' } }

Type Coercion

兩個等號會觸發 Type Coercion,將型別不同的值轉為同型別後再判斷真偽。

三個等號不會觸發 Type Coercion,判斷真偽時不會轉換型別。

console.log(1 == "1"); // true
console.log(1 === "1"); //false

判斷式經常使用 Type Coercion

// 因為字串會被轉換為 true,所以會ㄙ執行程式區塊內的代碼。
if ("Type Coercion") {
console.log(true);
}

有趣的對照表:

JS Comparison Table

相等比較 - JavaScript | MDN

ECMAScript Language Specification - ECMA-262 Edition 5.1

Object.is(值 1, 值 2)

// Object.is() 比三等號更直觀
console.log(NaN === NaN); // false
console.log(Object.is(NaN, NaN)); // true

JTS: Dynamic vs Static Typing

動態語言:宣告變數時不需指定型別,如 JavaScript。

靜態語言:宣告變數時需指定型別,如 C 語言。

靜態語言的優點:代碼本身略有文件功能、通常產品較少 Bug 或 Error

靜態語言的缺點:開發流程較慢

// 靜態語言宣告函式的方法
function sum(a: number, b: number) {
return a + b;
}

JTS: Weakly vs Strongly Typed

強型別語言:不允許不同型別的值交互處理(例:字串與數字不能相加)

弱型別語言:允許不同型別的值交互處理(例:字串與數字可以相加)

  • 四個 JavaScript 的強型別解決方案 Flow TypeScript Elm ReasonML
  • TypeScript 的優勢