第92次TC39會議舉行,這些提案取得新進(jìn)展!
大家好,我是 CUGGZ。
TC39 是一個推動 JavaScript 發(fā)展的技術(shù)委員會,由各個主流瀏覽器廠商的代表構(gòu)成,其主要工作就是制定 ECMAScript 標(biāo)準(zhǔn)。TC39 每兩個月舉行一次面對面會議。9 月 13 日至 16 日,第 92 次 TC39 會議舉行,該會議上以下提案取得新進(jìn)展:
- Stage 3:Array.fromAsync。
- Stage 2:Well-Formed Unicode Strings,關(guān)于確定字符串是否是格式良好的 Unicode 的方法提議。
- Stage 1:Extractors ,ECMAScript 的提取器。
對于提案,從提出到最后被納入 ECMAScript 標(biāo)準(zhǔn),總共分為五步:
- stage0(strawman):任何TC39的成員都可以提交。
- stage1(proposal):進(jìn)入此階段就意味著這一提案被認(rèn)為是正式的了,需要對此提案的場景與API進(jìn)行詳盡的描述。
- stage2(draft):演進(jìn)到這一階段的提案如果能最終進(jìn)入到標(biāo)準(zhǔn),那么在之后的階段都不會有太大的變化,因為理論上只接受增量修改。
- state3(candidate):這一階段的提案只有在遇到了重大問題才會修改,規(guī)范文檔需要被全面的完成。
- state4(finished):這一階段的提案將會被納入到ES每年發(fā)布的規(guī)范之中。
1、Array.fromAsync
在 JavaScript 中內(nèi)置了 Array.from 方法,它用于將類數(shù)組或者可迭代對象生成一個新的數(shù)組實例。在ECMAScript 2018中引入了異步可迭代對象。而JavaScript中一直缺少直接從異步可迭代對象生成數(shù)組的內(nèi)置方法。proposal-array-from-async 提案中提出來的 Array.fromAsync 方法就是為了解決這個問題而提出來的。
下面來看一個簡單的例子:
async function * asyncGen (n) {
for (let i = 0; i < n; i++)
yield i * 2;
}
// arr 將變?yōu)?[0, 2, 4, 6]`
const arr = [];
for await (const v of asyncGen(4)) {
arr.push(v);
}
// 與上述方式是等價的
const arr = await Array.fromAsync(asyncGen(4));
Array.fromAsync? 可以將異步迭代轉(zhuǎn)換為 promise?,并將解析為新數(shù)組。在 promise 解析之前,它將從輸入值中創(chuàng)建一個異步迭代器,進(jìn)行惰性的迭代,并將每個產(chǎn)生的值添加到新數(shù)組中。
與其他基于 Promise 的 API 一樣,Array.fromAsync? 總是會立即返回一個 promise?。當(dāng) Array.fromAsync? 的輸入在創(chuàng)建其異步或同步迭代器時引發(fā)錯誤時,則此 promise? 狀態(tài)將被置為 rejected。
提案地址:https://github.com/tc39/proposal-array-from-async?。
2、Well-Formed Unicode Strings
ECMAScript 中的字符串都是 UTF-16 編碼的,ECMAScript 對整數(shù)值沒有任何限制或要求,除非它們必須是 16 位無符號整數(shù)。在格式良好的字符串中,序列中的每個整數(shù)值代表一個 UTF-16 編碼的 Unicode 文本的 16 位代碼單元。但是,并非所有 UTF-16 代碼單元序列都表示 UTF-16 編碼的 Unicode 文本。在格式良好的字符串中,0xD800..0xDBFF 和 0xDC00..0xDFFF范圍內(nèi)的代碼單元必須成對出現(xiàn),并按順序排列。具有不成對或無序代理項的字符串是格式不正確。
在 JavaScript 中,這可以通過正則表達(dá)式 test 來實現(xiàn):
!/\p{Surrogate}/u.test(str);
或者使用以下算法:
function isWellFormed(str) {
for (let i = 0; i < str.length; ++i) {
const isSurrogate = (str.charCodeAt(i) & 0xF800) == 0xD800;
if (!isSurrogate) {
continue;
}
const isLeadingSurrogate = str.charCodeAt(i) < 0xDC00;
if (!isLeadingSurrogate) {
return false; // unpaired trailing surrogate
}
const isFollowedByTrailingSurrogate = i + 1 < str.length && (str.charCodeAt(i + 1) & 0xFC00) == 0xDC00;
if (!isFollowedByTrailingSurrogate) {
return false; // unpaired leading surrogate
}
++i;
}
return true;
}
目前沒有內(nèi)置的 API 可以實現(xiàn)這一點。因此,Well-Formed Unicode Strings 提案就是在 ECMA-262 中定義一種方法來驗證給定的 ECMAScript 字符串是否格式正確。它提出了兩個新方法[1]:
- String.prototype.isWellFormed():用于判斷字符串格式是否正確。
- String.prototype.toWellFormed() :用于將字符串轉(zhuǎn)換為正確格式。
提案地址:https://github.com/tc39/proposal-is-usv-string
3、Extractors
ECMAScript 目前沒有在解構(gòu)期間執(zhí)行用戶定義邏輯的機(jī)制,這意味著與數(shù)據(jù)驗證和轉(zhuǎn)換相關(guān)的操作可能需要多個語句:
function toInstant(value) {
if (value instanceof Temporal.Instant) {
return value;
} else if (value instanceof Date) {
return Temporal.Instant.fromEpochMilliseconds(+value);
} else if (typeof value === "string") {
return Temporal.Instant.from(value);
} else {
throw new TypeError();
}
}
class Book {
constructor({
isbn,
title,
createdAt = Temporal.Now.instant(),
modifiedAt = createdAt
}) {
this.isbn = isbn;
this.title = title;
this.createdAt = toInstant(createdAt);
// 如果 `modifiedAt` 是 `undefined`,就會重復(fù)一些工作
this.modifiedAt = toInstant(modifiedAt);
}
}
new Book({ isbn: "...", title: "...", createdAt: Temporal.Instant.from("...") });
new Book({ isbn: "...", title: "...", createdAt: new Date() });
new Book({ isbn: "...", title: "...", createdAt: "..." });
Extractors for ECMAScript 提案就是在 ECMAScript 中引入提取器(又名“提取器對象”)。提取器將增加 BindingPattern 和 AssignmentPattern 的語法以允許新的解構(gòu)形式,如下例所示:
// binding patterns
const Foo(y) = x; // instance-array destructuring
const Foo{y} = x; // instance-object destructuring
const [Foo(y)] = x; // nesting
const [Foo{y}] = x; // ..
const { z: Foo(y) } = x; // ..
const { z: Foo{y} } = x; // ..
const Foo(Bar(y)) = x; // ..
const X.Foo(y) = x; // qualified names (i.e., a.b.c)
// assignment patterns
Foo(y) = x; // instance-array destructuring
Foo{y} = x; // instance-object destructuring
[Foo(y)] = x; // nesting
[Foo{y}] = x; // ..
({ z: Foo(y) } = x); // ..
({ z: Foo{y} } = x); // ..
Foo(Bar(y)) = x; // ..
X.Foo(y) = x; // qualified names (i.e., a.b.c)
此外,這將利用 Pattern Matching 提案[2] 新添加的 Symbol.matcher?。使用新形式進(jìn)行解構(gòu)時,將調(diào)用 Symbol.matcher 方法,并將其結(jié)果進(jìn)行解構(gòu)。
使用 Extractors,可以在綁定模式中封裝和重用驗證和轉(zhuǎn)換邏輯:
const InstantExtractor = {
[Symbol.matcher]: value =>
value instanceof Temporal.Instant ? { matched: true, value: [value] } :
value instanceof Date ? { matched: true, value: [Temporal.Instant.fromEpochMilliseconds(value.getTime())] } :
typeof value === "string" ? { matched: true, value: [Temporal.Instant.from(value)] } :
{ matched: false };
}
};
class Book {
constructor({
isbn,
title,
createdAt: InstantExtractor(createdAt) = Temporal.Now.instant(),
modifiedAt: InstantExtractor(modifiedAt) = createdAt
}) {
this.isbn = isbn;
this.title = title;
this.createdAt = createdAt;
this.modifiedAt = modifiedAt;
}
}
new Book({ isbn: "...", title: "...", createdAt: Temporal.Instant.from("...") });
new Book({ isbn: "...", title: "...", createdAt: new Date() });
new Book({ isbn: "...", title: "...", createdAt: "..." });
提案地址:https://github.com/tc39/proposal-extractors。
?相關(guān)鏈接:
[1] isWellFormed()?和toWellFormed():https://tc39.es/proposal-is-usv-string/。
[2] Pattern Matching 提案:https://github.com/tc39/proposal-pattern-matching?。