このページ内容は2021年1月21日以降、再調査・再検証してません。実際に扱う際は最新の情報にアクセスしてください。
ECMAScriptのブラウザの対応状況はこちらのサイトecmascript_browser_supportから確認できます。ECMAScript2022まで出ていますが、現在のIEのことSafariが未対応の部分があるため、今回はES2021までの紹介に留めます。
数値に対して区切り線を付けることができるようになりましたnumeric_separators。_ を使って、整数や浮動小数点に対して使うことができます。こちらはデスクトップブラウザ、Node.js 12.11以上、iOS 13以上、Samsung 12以上で利用可能です。
10.000_001 === 0.000001 // true2100_000 === 100000 // true
これは文字置換に関するメソッドで、第一引数に変換前の文字、第二引数に変換後の文字を取ります。電話番号やURLのクエリパラメーターなどで記号 (-や+) を取り除きたいときに使えます。String.prototype.replaceでも同じことができますが、全ての文字を変換したい需要が高いため、生まれましたreplace_all_motivation。
Safariを含め主要なデスクトップブラウザでは対応済みです。Node.jsの方でもNode 15以上から利用できます。Mobileに関しては一部未対応の部分もあります。
従来のreplaceで書く場合は以下のようにします。
1const queryString = 'q=query+string+parameters';2const withSpaces = queryString.replace(/\+/g, ' '); // q=query string parameters
replaceAllを使う場合は次のように書くことができます。正規表現も使えますが、グローバルにしない場合 (gを付けない場合) はエラーを返しますreplace_all。
1const queryString = 'q=query+string+parameters';2const withSpaces = queryString.replaceAll('+', ' '); // q=query string parameters
Rubyの記法に触発されて生まれたもので、それぞれ以下の省略形ですlogical_assignment。
1a ||= 'default' // a || (a = 'default')の省略形23a &&= 'default' // a && (a = 'default')の省略形45a ??= 'default' // a ?? (a = 'default')の省略形
a ||= b
は a
がfalthyな値ならb
で上書きするという意味です。falthyというのは、!!a
がfalseになる値のことで、null, undefined, false, 空文字などが該当します。
1const a = null2const b = undefined3const c = false4const d = ''5const e = 'test'67// ['default', 'default', 'default', 'default', 'test']8[a, b, c, d, e].map(value => value ||= 'default')
a ??=b
は a
がnullかundefinedのときにb
で上書きするという意味です。
1const a = null2const b = undefined3const c = false4const d = ''5const e = 'test'67// ['default', 'default', false, '', 'test']8[a, b, c, d, e].map(value => value ??= 'default')
最後に a &&= b
は a
がtruthyなときにb
で上書きするという意味です。Logical AssignmentもreplaceAllと同じでデスクトップブラウザやNode15.0以上では対応してますが、モバイルでは一部対応していません。
1const a = null2const b = undefined3const c = false4const d = ''5const e = 'test'67// [null, undefined, false, '', 'default']8[a, b, c, d, e].map(value => value &&= 'default')
異なるユースケースに対応するために追加されました。引数にPromiseの配列を取り、引数のPromiseのいずれかがresolveするまで待ちますpromise_any。こちらも対応状況はLogical AssignmentやreplaceAllと同じで、一部モバイルには対応してません。
以下のようにして使います。
1const reject1 = new Promise((resolve, reject) => setTimeout(reject, 500, 'reject1'))2const resolve1 = new Promise((resolve) => setTimeout(resolve, 1000, 'resolve1'))3const reject2 = new Promise((resolve, reject) => setTimeout(reject, 1500, 'reject2'))4const resolve2 = new Promise((resolve) => setTimeout(resolve, 2000, 'resolve2'))56const first = await Promise.any([reject1, reject2, resolve1, resolve2])7console.log(first) // resolve1
この他にもES2020にはPromise.allSettled, ES2015にはPromise.all, Promise.raceが追加されています。Promise.allSettledは与えられた全てのPromiseの結果を配列で返すもので、全てのリクエストが成功したか、それとも一部失敗したのかを知りたいときに使えますpromise_all_settled。
1const reject1 = new Promise((resolve, reject) => setTimeout(reject, 500, 'reject1'))2const resolve1 = new Promise((resolve) => setTimeout(resolve, 1000, 'resolve1'))3const reject2 = new Promise((resolve, reject) => setTimeout(reject, 1500, 'reject2'))4const resolve2 = new Promise((resolve) => setTimeout(resolve, 2000, 'resolve2'))56const results = await Promise.allSettled([reject1, reject2, resolve1, resolve2]);7const errors = results8.filter(p => p.status === 'rejected')9.map(p => p.reason);10console.log(errors) // ['reject1', 'reject2']
Promise.raceは全てのPromiseの中で一番最初にresolveまたはrejectされたものを返すPromiseですpromise_race。
1const reject1 = new Promise((resolve, reject) => setTimeout(reject, 500, 'reject1'))2const resolve1 = new Promise((resolve) => setTimeout(resolve, 1000, 'resolve1'))3const reject2 = new Promise((resolve, reject) => setTimeout(reject, 1500, 'reject2'))4const resolve2 = new Promise((resolve) => setTimeout(resolve, 2000, 'resolve2'))56try {7const first = await Promise.any([reject1, reject2, resolve1, resolve2])8console.log(first)9} catch (e) {10console.log(`error: ${e}`) // error: reject111}
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。
1const reject1 = new Promise((resolve, reject) => setTimeout(reject, 2500, 'reject1'))2const resolve1 = new Promise((resolve) => setTimeout(resolve, 1000, 'resolve1'))3const resolve2 = new Promise((resolve) => setTimeout(resolve, 2000, 'resolve2'))45try {6const first = await Promise.all([reject1, resolve1, resolve2])7console.log(first)8} catch (e) {9console.log(`error: ${e}`) // error: reject110}
1const resolve1 = new Promise((resolve) => setTimeout(resolve, 1000, 'resolve1'))2const resolve2 = new Promise((resolve) => setTimeout(resolve, 2000, 'resolve2'))34try {5const first = await Promise.all([resolve1, resolve2])6console.log(first) // ['resolve1', 'resolve2']7} catch (e) {8console.log(`error: ${e}`)9}
ES2021では他にも弱参照に関する追加がありましたが、使う機会が限られると思うため、紹介しません。詳細はGitHubにありますweak_ref。