このページ内容は2021年1月21日以降、再調査・再検証してません。実際に扱う際は最新の情報にアクセスしてください。

link
ES2021

ECMAScriptのブラウザの対応状況はこちらのサイトecmascript_browser_supportから確認できます。ECMAScript2022まで出ていますが、現在のIEのことSafariが未対応の部分があるため、今回はES2021までの紹介に留めます。

link
Numeric Separators

数値に対して区切り線を付けることができるようになりましたnumeric_separators。_ を使って、整数や浮動小数点に対して使うことができます。こちらはデスクトップブラウザ、Node.js 12.11以上、iOS 13以上、Samsung 12以上で利用可能です。

1
0.000_001 === 0.000001 // true
2
100_000 === 100000 // true
link
String.prototype.replaceAll

これは文字置換に関するメソッドで、第一引数に変換前の文字、第二引数に変換後の文字を取ります。電話番号やURLのクエリパラメーターなどで記号 (-や+) を取り除きたいときに使えます。String.prototype.replaceでも同じことができますが、全ての文字を変換したい需要が高いため、生まれましたreplace_all_motivation

Safariを含め主要なデスクトップブラウザでは対応済みです。Node.jsの方でもNode 15以上から利用できます。Mobileに関しては一部未対応の部分もあります。

従来のreplaceで書く場合は以下のようにします。

1
const queryString = 'q=query+string+parameters';
2
const withSpaces = queryString.replace(/\+/g, ' '); // q=query string parameters

replaceAllを使う場合は次のように書くことができます。正規表現も使えますが、グローバルにしない場合 (gを付けない場合) はエラーを返しますreplace_all

1
const queryString = 'q=query+string+parameters';
2
const withSpaces = queryString.replaceAll('+', ' '); // q=query string parameters
link
Logical Assignment

Rubyの記法に触発されて生まれたもので、それぞれ以下の省略形ですlogical_assignment

1
a ||= 'default' // a || (a = 'default')の省略形
2
3
a &&= 'default' // a && (a = 'default')の省略形
4
5
a ??= 'default' // a ?? (a = 'default')の省略形

a ||= baがfalthyな値ならbで上書きするという意味です。falthyというのは、!!aがfalseになる値のことで、null, undefined, false, 空文字などが該当します。

1
const a = null
2
const b = undefined
3
const c = false
4
const d = ''
5
const e = 'test'
6
7
// ['default', 'default', 'default', 'default', 'test']
8
[a, b, c, d, e].map(value => value ||= 'default')

a ??=baがnullかundefinedのときにbで上書きするという意味です。

1
const a = null
2
const b = undefined
3
const c = false
4
const d = ''
5
const e = 'test'
6
7
// ['default', 'default', false, '', 'test']
8
[a, b, c, d, e].map(value => value ??= 'default')

最後に a &&= baがtruthyなときにbで上書きするという意味です。Logical AssignmentもreplaceAllと同じでデスクトップブラウザやNode15.0以上では対応してますが、モバイルでは一部対応していません。

1
const a = null
2
const b = undefined
3
const c = false
4
const d = ''
5
const e = 'test'
6
7
// [null, undefined, false, '', 'default']
8
[a, b, c, d, e].map(value => value &&= 'default')
link
Promise.any

異なるユースケースに対応するために追加されました。引数にPromiseの配列を取り、引数のPromiseのいずれかがresolveするまで待ちますpromise_any。こちらも対応状況はLogical AssignmentやreplaceAllと同じで、一部モバイルには対応してません。

以下のようにして使います。

1
const reject1 = new Promise((resolve, reject) => setTimeout(reject, 500, 'reject1'))
2
const resolve1 = new Promise((resolve) => setTimeout(resolve, 1000, 'resolve1'))
3
const reject2 = new Promise((resolve, reject) => setTimeout(reject, 1500, 'reject2'))
4
const resolve2 = new Promise((resolve) => setTimeout(resolve, 2000, 'resolve2'))
5
6
const first = await Promise.any([reject1, reject2, resolve1, resolve2])
7
console.log(first) // resolve1

この他にもES2020にはPromise.allSettled, ES2015にはPromise.all, Promise.raceが追加されています。Promise.allSettledは与えられた全てのPromiseの結果を配列で返すもので、全てのリクエストが成功したか、それとも一部失敗したのかを知りたいときに使えますpromise_all_settled

1
const reject1 = new Promise((resolve, reject) => setTimeout(reject, 500, 'reject1'))
2
const resolve1 = new Promise((resolve) => setTimeout(resolve, 1000, 'resolve1'))
3
const reject2 = new Promise((resolve, reject) => setTimeout(reject, 1500, 'reject2'))
4
const resolve2 = new Promise((resolve) => setTimeout(resolve, 2000, 'resolve2'))
5
6
const results = await Promise.allSettled([reject1, reject2, resolve1, resolve2]);
7
const errors = results
8
.filter(p => p.status === 'rejected')
9
.map(p => p.reason);
10
console.log(errors) // ['reject1', 'reject2']

Promise.raceは全てのPromiseの中で一番最初にresolveまたはrejectされたものを返すPromiseですpromise_race

1
const reject1 = new Promise((resolve, reject) => setTimeout(reject, 500, 'reject1'))
2
const resolve1 = new Promise((resolve) => setTimeout(resolve, 1000, 'resolve1'))
3
const reject2 = new Promise((resolve, reject) => setTimeout(reject, 1500, 'reject2'))
4
const resolve2 = new Promise((resolve) => setTimeout(resolve, 2000, 'resolve2'))
5
6
try {
7
const first = await Promise.any([reject1, reject2, resolve1, resolve2])
8
console.log(first)
9
} catch (e) {
10
console.log(`error: ${e}`) // error: reject1
11
}

Promise.allは全てのPromiseの結果がresolveされたときに、Promiseの結果の配列を返すものです。ただ、1つでもrejectされたものがあれば、その時点でエラーを返しますpromise_all。Promiseが1つでも失敗したら、すぐに止めたい場合はPromise.allを使い、全て実行した後に失敗したものをリトライしたい場合はPromise.allSettledという使い分けができそうです。

余談ですが、これらの省略表記であるawait.all, await.race, await.allSettled, await.anyなども提案されていますpromise_await

1
const reject1 = new Promise((resolve, reject) => setTimeout(reject, 2500, 'reject1'))
2
const resolve1 = new Promise((resolve) => setTimeout(resolve, 1000, 'resolve1'))
3
const resolve2 = new Promise((resolve) => setTimeout(resolve, 2000, 'resolve2'))
4
5
try {
6
const first = await Promise.all([reject1, resolve1, resolve2])
7
console.log(first)
8
} catch (e) {
9
console.log(`error: ${e}`) // error: reject1
10
}
1
const resolve1 = new Promise((resolve) => setTimeout(resolve, 1000, 'resolve1'))
2
const resolve2 = new Promise((resolve) => setTimeout(resolve, 2000, 'resolve2'))
3
4
try {
5
const first = await Promise.all([resolve1, resolve2])
6
console.log(first) // ['resolve1', 'resolve2']
7
} catch (e) {
8
console.log(`error: ${e}`)
9
}

ES2021では他にも弱参照に関する追加がありましたが、使う機会が限られると思うため、紹介しません。詳細はGitHubにありますweak_ref


自己紹介
はじめまして Pilefortです。
東京でエソジニアをしてます。
興味のあるスタックは、JavaScript (React, Vue), TypeScript, Rust, WebAssembly, AWS, Pulumi, Serverless Frameworkです。
このブログでは、普段の業務や趣味で気になったことをまとめたり、フロントやAWS, GitHubやTwitterで見かけた面白い記事やニュースをまとめるためのものです。少しでも何かの役に立てば幸いです。
サイトマップ
Notes
業務や趣味での気づき・メモ
Snippets
記事にするまでもないけど、便利なコマンドや豆知識
Works
同人誌一覧