2019:ECMAScript 2019——扁平化陣列#
事件#
2019年6月,ECMAScript 2019(ES10) 發佈,主軸是陣列扁平化與「程式碼衛生」類的小改進。
新語法與特性#
1. Array.prototype.flat / flatMap#
- 為何加入:巢狀陣列扁平化以前要手寫遞迴或用
[].concat.apply([], arr)駭客寫法(且多層巢狀無法一次攤平)。 - 理論原因:
flatMap是 map + flatten 的組合,源自函數式語言(Scala、Haskell 的 bind/join 傳統),是單子(monad)操作在大眾語言中的罕見現身。 - 實用原因:JSON 資料解析(樹狀結構攤平成清單)、多層分組資料的處理。
- 彌補缺陷:巢狀陣列處理工具缺失與 concat 駭客寫法。
2. Object.fromEntries#
- 為何加入:ES2017 有
Object.entries(物件→陣列),反方向(陣列→物件)要手寫 reduce。 - 理論原因:與
entries對稱,完成「物件↔鍵值對陣列」的雙向轉換迴路。 - 實用原因:Map↔Object 轉換、查詢字串解析(
URLSearchParams→ 物件)。 - 彌補缺陷:物件轉換 API 的不對稱。
3. String.trimStart / trimEnd#
- 為何加入:ES5 只有
trim()(兩端都修剪),只需修一端時要手寫 regex。 - 理論原因:借鑑 Python 的
lstrip/rstrip命名傳統。 - 彌補缺陷:單端修剪工具缺失。
4. try...catch 可省略 catch 綁定(optional catch binding)#
- 為何加入:很多時候不需要錯誤物件,卻被迫寫
catch (e)——未使用的變數是語法噪音。 - 實用原因:
try { JSON.parse(s) } catch { return null }這類「失敗就放棄」模式更簡潔。 - 彌補缺陷:強制綁定造成未使用變數的語法噪音。
5. 其他#
Symbol.prototype.description、Array.prototype.sort等方法的穩定性要求(stable sort 成為規範)、JSON.stringify 的 Unicode 修正、Function.prototype.toString精確化。
理論總結#
ES2019 的主軸是「對稱補齊與程式碼衛生」:fromEntries 補齊 entries 的反面、flat 補齊巢狀處理、可省略 catch 綁定消除語法噪音。語言進入「打磨期」——大架構(ES6–ES8)已定,剩餘的是精緻化。
實用總結#
這一年的特性都不改變程式設計範式,但每一項都消除一個常見的駭客寫法(concat.apply、[\s\S]、var self),實際上減少了生態中「樣板與陷阱」的存量。
相關條目#
程式範例#
1. flat / flatMap:巢狀陣列的解法#
// ES2018 之前:concat 駭客寫法(只能攤一層)
[1, [2, 3], [4, [5]]].concat.apply([], [[1], [2]]); // 複雜且多層無法一次攤平
// ES2019:flat
[1, [2, 3], [4, [5]]].flat(); // [1, 2, 3, 4, [5]]——攤一層
[1, [2, [3, [4]]]].flat(Infinity); // [1, 2, 3, 4]——全攤平
// flatMap:map + flatten(函數式的 monad 操作)
["hello world", "foo bar"].flatMap((s) => s.split(" "));
// ["hello", "world", "foo", "bar"]——map 之後再攤平,一行完成
2. Object.fromEntries:物件↔陣列的雙向迴路#
// ES2017 有 entries,反方向要手寫 reduce
Object.entries({ a: 1, b: 2 }); // [["a",1], ["b",2]]——物件→陣列
// ES2019:fromEntries——陣列→物件
Object.fromEntries([["a", 1], ["b", 2]]); // { a: 1, b: 2 }
// 實用案例:Map↔Object 轉換、URL 查詢字串解析
const params = new URLSearchParams("?a=1&b=2");
Object.fromEntries(params); // { a: "1", b: "2" }
3. 可省略 catch 綁定:消除語法噪音#
// ES2018:不需要錯誤物件也要寫 catch (e)
try { JSON.parse(text) } catch (e) { return null }
// ES2019:直接省略
try { JSON.parse(text) } catch { return null }
4. trimStart / trimEnd#
" hi ".trim(); // "hi"(ES5,兩端)
" hi ".trimStart(); // "hi "(只修左端——Python lstrip 對照)
" hi ".trimEnd(); // " hi"