JavaScript 的型別
JavaScript Types
// 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);
}
有趣的對照表:
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 的優勢