TC39 的提案筆者一直有關注,攢了一些有趣的今天來聊聊。git
PS:提案總共五個階段,只有到階段 4 纔會被歸入到發佈規範中,其它的只是有概率會被歸入。github
這是個挺不錯的新語法。其餘有些語言是能夠用 arr[-1]
來獲取數組末尾的元素,可是對於 JS 來講這是實現不了的事情。由於 [key]
對於對象來講就是在獲取 key
對應的值。數組也是對象,對於數組使用 arr[-1]
就是在獲取 key
爲 -1
的值。web
因爲以上緣由,咱們想獲取末尾元素就得這樣寫 arr[arr.length - 1]
,之後有了 at
這個方法,咱們就能夠經過 arr.at(-1)
來拿末尾的元素了,另外一樣適用類數組、字符串。編程
// Polyfill
function at(n) {
// ToInteger() abstract op
n = Math.trunc(n) || 0;
// Allow negative indexing from the end
if(n < 0) n += this.length;
// OOB access is guaranteed to return undefined
if(n < 0 || n >= this.length) return undefined;
// Otherwise, this is just normal property access
return this[n];
}
複製代碼
await
都得用 async
函數包裹你們確定都知道,這個限制致使咱們不能在全局做用域下直接使用 await
,必須得包裝一下。api
有了這個提案之後,你們就能夠直接在頂層寫 await
了,算是一個便利性的提案。數組
目前該提案已經進入階段 4,板上釘釘會發布。另外其實 Chrome 近期的更新已經支持了該功能。性能優化
這個語法主要幫助咱們便捷地傳遞 Error。一旦可能出錯的地方一多,咱們實際就不清楚錯誤究竟是哪裏產生的。若是但願外部清楚的知道上下文信息的話,咱們須要封裝如下 error。markdown
async function getSolution() {
const rawResource = await fetch('//domain/resource-a')
.catch(err => {
// How to wrap the error properly?
// 1. throw new Error('Download raw resource failed: ' + err.message);
// 2. const wrapErr = new Error('Download raw resource failed');
// wrapErr.cause = err;
// throw wrapErr;
// 3. class CustomError extends Error {
// constructor(msg, cause) {
// super(msg);
// this.cause = cause;
// }
// }
// throw new CustomError('Download raw resource failed', err);
})
const jobResult = doComputationalHeavyJob(rawResource);
await fetch('//domain/upload', { method: 'POST', body: jobResult });
}
await doJob(); // => TypeError: Failed to fetch
複製代碼
那麼有了這個語法之後,咱們能夠這樣來簡化代碼:數據結構
async function doJob() {
const rawResource = await fetch('//domain/resource-a')
.catch(err => {
throw new Error('Download raw resource failed', { cause: err });
});
const jobResult = doComputationalHeavyJob(rawResource);
await fetch('//domain/upload', { method: 'POST', body: jobResult })
.catch(err => {
throw new Error('Upload job result failed', { cause: err });
});
}
try {
await doJob();
} catch (e) {
console.log(e);
console.log('Caused by', e.cause);
}
// Error: Upload job result failed
// Caused by TypeError: Failed to fetch
複製代碼
這個語法的 Star 特別多,有 5k 多個,側面也能說明是個受歡迎的語法,可是距離發佈應該還有很久,畢竟這個提案三四年前就有了,目前還只到階段 1。frontend
這個語法其實在其餘函數式編程語言上很常見,主要是爲了函數調用方便:
let result = exclaim(capitalize(doubleSay("hello")));
result //=> "Hello, hello!"
let result = "hello"
|> doubleSay
|> capitalize
|> exclaim;
result //=> "Hello, hello!"
複製代碼
這只是對於單個參數的用法,其它的用法有興趣的讀者能夠自行閱讀提案,其中涉及到了特別多的內容,這大概也是致使推動階段慢的緣由吧。
這個數據結構筆者以爲發佈之後會特別有用,總共新增了兩種數據結構,咱們能夠經過 #
來聲明:
#{ x: 1, y: 2 }
#[1, 2, 3, 4]
這種數據結構是不可變的,相似 React 中爲了作性能優化會引入的 immer 或者 immutable.js,其中的值只接受基本類型或者同是不可變的數據類型。
const proposal = #{
id: 1234,
title: "Record & Tuple proposal",
contents: `...`,
// tuples are primitive types so you can put them in records:
keywords: #["ecma", "tc39", "proposal", "record", "tuple"],
};
// Accessing keys like you would with objects!
console.log(proposal.title); // Record & Tuple proposal
console.log(proposal.keywords[1]); // tc39
// Spread like objects!
const proposal2 = #{
...proposal,
title: "Stage 2: Record & Tuple",
};
console.log(proposal2.title); // Stage 2: Record & Tuple
console.log(proposal2.keywords[1]); // tc39
// Object functions work on Records:
console.log(Object.keys(proposal)); // ["contents", "id", "keywords", "title"]
複製代碼
以上筆者列舉了一部分有意思的 TC39 提案,除了以上這些還有不少提案,各位讀者有興趣的話能夠在 TC39 中尋找。