本週精讀的內容是:Google I/O 19。javascript
2019 年 Google I/O 介紹了一些激動人心的 JS 新特性,這些特性有些已經被主流瀏覽器實現,並支持 polyfill,有些還在草案階段。前端
咱們能夠看到 JS 語言正變得愈來愈嚴謹,不一樣規範間也逐漸完成了閉環,並且在不斷吸納其餘語言的優秀特性,好比 WeakRef,讓 JS 在成爲使用範圍最廣編程語言的同時,也越成爲編程語言的集大成者,讓咱們有信心繼續跟隨 JS 生態,不用被新生的小語種分散精力。java
本視頻共介紹了 16 個新特性。node
私有成員修飾符,用於 Class:git
class IncreasingCounter { #count = 0; get value() { return this.#count; } increment() { this.#count++; } }
經過 #
修飾的成員變量或成員函數就成爲了私有變量,若是試圖在 Class 外部訪問,則會拋出異常:程序員
const counter = new IncreasingCounter() counter.#count // -> SyntaxError counter.#count = 42 // -> SyntaxError
雖然 #
這個關鍵字被吐槽了不少次,但結論已經塵埃落定了,只是個語法形式而已,不用太糾結。github
目前僅 Chrome、Nodejs 支持。web
正則匹配支持了 matchAll
API,能夠更方便進行正則遞歸了:shell
const string = 'Magic hex number: DEADBEEF CAFE' const regex = /\b\p{ASCII_Hex_Digit}+\b/gu/ for (const match of string.matchAll(regex)) { console.log(match) } // Output: // ['DEADBEEF', index: 19, input: 'Magic hex number: DEADBEEF CAFE'] // ['CAFE', index: 28, input: 'Magic hex number: DEADBEEF CAFE']
相比之前在 while
語句裏循環正則匹配,這個 API 真的是至關的便利。And more,還順帶提到了 Named Capture Groups
,這個在以前的 精讀《正則 ES2018》 中也有提到,具體能夠點過去閱讀,也能夠配合 matchAll
一塊兒使用。編程
大數字面量的支持,好比:
1234567890123456789 * 123; // -> 151851850485185200000
這樣計算結果是丟失精度的,但只要在數字末尾加上 n
,就能夠正確計算大數了:
1234567890123456789n * 123n; // -> 151851850485185185047n
目前 BigInt 已經被 Chrome、Firefox、Nodejs 支持。
爲了方便閱讀,大數還支持了國際化,能夠適配成不一樣國家的語言表達形式:
const nf = new Intl.NumberFormat("fr"); nf.format(12345678901234567890n); // -> '12 345 678 901 234 567 890'
記住 Intl
這個內置變量,後面還有很多國際化用途。
同時,爲了方便程序員閱讀代碼,大數還支持帶下劃線的書寫方式:
const nf = new Intl.NumberFormat("fr"); nf.format(12345678901234567890n); // -> '12 345 678 901 234 567 890'
目前已經被 Chrome、Firefox、Nodejs 支持。
等價於 lodash flatten 功能:
const array = [1, [2, [3]]]; array.flat(); // -> [1, 2, [3]]
還支持自定義深度,若是支持 Infinity
無限層級:
const array = [1, [2, [3]]]; array.flat(Infinity); // -> [1, 2, 3]
這樣咱們就能夠配合 .map
使用:
[2, 3, 4].map(duplicate).flat();
由於這個用法太常見,js 內置了 flatMap
函數代替 map
,與上面的效果是等價的:
[2, 3, 4].flatMap(duplicate);
目前已經被 Chrome、Firefox、Safari、Nodejs 支持。
fromEntries
是 Object.fromEntries
的語法,用來將對象轉化爲數組的描述:
const object = { x: 42, y: 50, abc: 9001 }; const entries = Object.entries(object); // -> [['x', 42], ['y', 50]]
這樣就能夠對對象的 key 與 value 進行加工處理,並經過 fromEntries
API 從新轉回對象:
const object = { x: 42, y: 50, abc: 9001 } const result Object.fromEntries( Object.entries(object) .filter(([ key, value]) => key.length === 1) .map(([ key, value ]) => [ key, value * 2]) ) // -> { x: 84, y: 100 }
不只如此,還能夠將 object 快速轉化爲 Map:
const map = new Map(Object.entries(object));
目前已經被 Chrome、Firefox、Safari、Nodejs 支持。
fromEntries
創建了 object 與 map 之間的橋樑,咱們還能夠將 Map 快速轉化爲 object:
const objectCopy = Object.fromEntries(map);
目前已經被 Chrome、Firefox、Safari、Nodejs 支持。
業務代碼通常不須要訪問全局的 window 變量,可是框架與庫通常須要,好比 polyfill。
訪問全局的 this 通常會作四個兼容,由於 js 在不一樣運行環境下,全局 this 的變量名都不同:
const getGlobalThis = () => { if (typeof self !== "undefined") return self; // web worker 環境 if (typeof window !== "undefined") return window; // web 環境 if (typeof global !== "undefined") return global; // node 環境 if (typeof this !== "undefined") return this; // 獨立 js shells 腳本環境 throw new Error("Unable to locate global object"); };
所以整治一下規範也合情合理:
globalThis; // 在任何環境,它就是全局的 this
目前已經被 Chrome、Firefox、Safari、Nodejs 支持。
就是穩定排序結果的功能,好比下面的數組:
const doggos = [ { name: "Abby", rating: 12 }, { name: "Bandit", rating: 13 }, { name: "Choco", rating: 14 }, { name: "Daisy", rating: 12 }, { name: "Elmo", rating: 12 }, { name: "Falco", rating: 13 }, { name: "Ghost", rating: 14 } ]; doggos.sort((a, b) => b.rating - a.rating);
最終排序結果可能以下:
[ { name: "Choco", rating: 14 }, { name: "Ghost", rating: 14 }, { name: "Bandit", rating: 13 }, { name: "Falco", rating: 13 }, { name: "Abby", rating: 12 }, { name: "Daisy", rating: 12 }, { name: "Elmo", rating: 12 } ];
也可能以下:
[ { name: "Ghost", rating: 14 }, { name: "Choco", rating: 14 }, { name: "Bandit", rating: 13 }, { name: "Falco", rating: 13 }, { name: "Abby", rating: 12 }, { name: "Daisy", rating: 12 }, { name: "Elmo", rating: 12 } ];
注意 choco
與 Ghost
的位置可能會顛倒,這是由於 JS 引擎可能只關注 sort
函數的排序,而在順序相同時,不會保持原有的排序規則。如今經過 Stable sort 規範,能夠確保這個排序結果是穩定的。
目前已經被 Chrome、Firefox、Safari、Nodejs 支持。
Intl.RelativeTimeFormat
能夠對時間進行語義化翻譯:
const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" }); rtf.format(-1, "day"); // -> 'yesterday' rtf.format(0, "day"); // -> 'today' rtf.format(1, "day"); // -> 'tomorrow' rtf.format(-1, "week"); // -> 'last week' rtf.format(0, "week"); // -> 'this week' rtf.format(1, "week"); // -> 'next week'
不一樣語言體系下,format
會返回不一樣的結果,經過控制 RelativeTimeFormat
的第一個參數 en
決定,好比能夠切換爲 ta-in
。
ListFormat
以列表的形式格式化數組:
const lfEnglish = new Intl.ListFormat("en"); lfEnglish.format(["Ada", "Grace"]); // -> 'Ada and Grace'
能夠經過第二個參數指定鏈接類型:
const lfEnglish = new Intl.ListFormat("en", { type: "disjunction" }); lfEnglish.format(["Ada", "Grace"]); // -> 'Ada or Grace'
目前已經被 Chrome、Nodejs 支持。
DateTimeFormat
能夠定製日期格式化輸出:
const start = new Date(startTimestamp); // -> 'May 7, 2019' const end = new Date(endTimestamp); // -> 'May 9, 2019' const fmt = new Intl.DateTimeFormat("en", { year: "numeric", month: "long", day: "numeric" }); const output = `${fmt.format(start)} - ${fmt.format(end)}`; // -> 'May 7, 2019 - May 9, 2019'
最後一句,也能夠經過 formatRange
函數代替:
const output = fmt.formatRange(start, end); // -> 'May 7 - 9, 2019'
目前已經被 Chrome 支持。
定義國際化本地化的相關信息:
const locale = new Intl.Locale("es-419-u-hc-h12", { calendar: "gregory" }); locale.language; // -> 'es' locale.calendar; // -> 'gregory' locale.hourCycle; // -> 'h12' locale.region; // -> '419' locale.toString(); // -> 'es-419-u-ca-gregory-hc-h12'
目前已經被 Chrome、Nodejs 支持。
支持在根節點生效 await
,好比:
const result = await doSomethingAsync(); doSomethingElse();
目前尚未支持。
Promise.allSettled
相似 Promise.all
、Promise.any
相似 Promise.race
,區別是,在 Promise reject 時,allSettled
不會 reject,而是也看成 fulfilled 的信號。
舉例來講:
const promises = [ fetch("/api-call-1"), fetch("/api-call-2"), fetch("/api-call-3") ]; await Promise.allSettled(promises);
即使某個 fetch
失敗了,也不會致使 reject
的發生,這樣在不在意是否有項目失敗,只要拿到都結束的信號的場景頗有用。
對於 Promise.any
則稍有不一樣:
const promises = [ fetch("/api-call-1"), fetch("/api-call-2"), fetch("/api-call-3") ]; try { const first = await Promise.any(promises); // Any of ths promises was fulfilled. console.log(first); } catch (error) { // All of the promises were rejected. }
只要有子項 fulfilled,就會完成 Promise.any
,哪怕第一個 Promise reject 了,而第二個 Promise fulfilled 了,Promise.any
也會 fulfilled,而對於 Promise.race
,這種場景會直接 rejected。
若是全部子項都 rejected,那 Promise.any
也只好 rejected 啦。
目前已經被 Chrome、Firefox 支持。
WeakRef 是從 OC 抄過來的弱引用概念。
爲了解決這個問題:當對象被引用後,因爲引用的存在,致使對象沒法被 GC。
因此若是創建了弱引用,那麼對象就不會由於存在的這段引用關係而影響 GC 了!
具體用法是:
const obj = {}; const weakObj = new WeakRef(obj);
使用 weakObj
與 obj
沒有任何區別,惟一不一樣時,obj
可能隨時被 GC,而一旦被 GC,弱引用拿到的對象可能就變成 undefined
,因此要作好錯誤保護。
JS 這幾個特性提高了 JS 語言的成熟性、完整性,並且看到其訪問控制能力、規範性、國際化等能力有着重增強,解決的都是 JS 最廣泛遇到的痛點問題。
那麼,這些 JS 特性中,你最喜歡哪一條呢?想吐槽哪一條呢?歡迎留言。
討論地址是: 精讀《What's new in javascript》 · Issue #159 · dt-fe/weekly
若是你想參與討論,請 點擊這裏,每週都有新的主題,週末或週一發佈。前端精讀 - 幫你篩選靠譜的內容。
關注 前端精讀微信公衆號
<img width=200 src="https://img.alicdn.com/tfs/TB...;>
special Sponsors
版權聲明:自由轉載-非商用-非衍生-保持署名( 創意共享 3.0 許可證)