昨天提到了 ES6 的 Class
super
語法糖,今天來繼續看 ES6 還有什麼其他的語法。
解構賦值可以從陣列或物件中快速提取值,並直接指派給變數。
用在物件
用在陣列
使用 ...
來展開陣列或物件,或收集剩餘的值。
陣列展開
const arr1 = [1, 2];
const arr2 = [...arr1, 3, 4]; // [1, 2, 3, 4]
物件合併
const base = { a: 1, b: 2 };
const extended = { ...base, c: 3 }; // { a: 1, b: 2, c: 3 }
函式參數收集
function sum(...nums) {
return nums.reduce((a, b) => a + b, 0);
}
sum(1, 2, 3); // 6
concat()
、Object.assign()
等繁瑣寫法const { a, ...rest } = { a: 1, b: 2, c: 3 };
// a = 1, rest = { b: 2, c: 3 }
這麼寫的好處,除了可以取代重複的 obj.property、
減少程式碼,使得程式碼更簡潔。然而,在 React 中必須特別注意!因為 React 中的狀態都應該要是 immutable 的,才能使狀態改變時去 trigger 全面重新繪製。但是假設今天使用巢狀 array 或是巢狀物件,在做比較的時候,會對 reference 進行比較,因此即便裡頭的某些值發生改變,子層級的 reference 維持相同,即違反了 immutable 的原則。
假設我們有這個狀態:
const [state, setState] = useState({
app: {
user: {
profile: {
settings: {
notifications: {
email: true,
push: false,
sms: true
}
}
}
}
}
});
當我們想要把 push
改成 true 時,若使用展開式且需要同時尊循 immutable 的特性時,那我們就會寫出難以閱讀、難以維護的程式碼
setAppState({
...appState,
user: {
...appState.user,
profile: {
...appState.user.profile,
personal: {
...appState.user.profile.personal,
contact: {
...appState.user.profile.personal.contact,
address: {
...appState.user.profile.personal.contact.address,
city: 'Kaohsiung'
}
}
}
}
}
});
模組化讓程式碼拆分成可重用的模組。ESM 是 ES6 的標準模組系統,而 CommonJS 是 Node.js 傳統使用的模組系統。
比較項 | ESM (ES Modules) | CommonJS |
---|---|---|
語法 | import / export |
require / module.exports |
載入 | 靜態載入(compile-time) | 動態載入(runtime) |
是否支援 tree-shaking | 是 | 否 |
Tree Shaking 是個優化的方式,在JavaScript 中用來表示移除沒用的程式碼
ESM
// math.js
export function add(a, b) { return a + b; }
// main.js
import { add } from './math.js';
console.log(add(2, 3)); // 5
CommonJS
// math.js
function add(a, b) { return a + b; }
module.exports = { add };
// main.js
const { add } = require('./math');
console.log(add(2, 3)); // 5
Proxy
可攔截物件的操作(如存取屬性、設值),讓你能自定義行為;Reflect
則是用來統一這些底層操作的方法。
Reflect 搭配 Proxy
Proxy
+ Reflect
讓攔截更一致、可預測Symbol
是 ES6 引入的一種唯一值,常用於建立不會與其他屬性衝突的物件 key,適合做私有屬性、常數、meta programming。像是以下的範例, Symbol
規範住的屬性將不會被列舉。
讓物件可被 for...of
、spread
使用,實作 [Symbol.iterator]()
方法即可。
一種「可暫停執行」的函式。用 function*
宣告,搭配 yield
控制流程。