トップレベルの`await`
トップレベルのawait
は、開発者が非同期関数の外部でawait
キーワードを使用できるようにします。それは、他のモジュールがそれらをimport
する際に、モジュールのボディを評価する前に待機する大きな非同期関数のように動作します。
トップレベルのawait
は、開発者が非同期関数の外部でawait
キーワードを使用できるようにします。それは、他のモジュールがそれらをimport
する際に、モジュールのボディを評価する前に待機する大きな非同期関数のように動作します。
ヌリッシュ合体提案 nullish coalescing proposal (??
) は、デフォルト値を処理するために設計された新しいショートサーキット演算子を追加します。
既に他のショートサーキット演算子 &&
と ||
に慣れているかもしれません。これらの両演算子は「truthy」と「falsy」の値を扱います。コード例 lhs && rhs
を想像してください。もし lhs
(左辺) が falsy なら、式は lhs
を評価します。それ以外の場合、式は rhs
(右辺) を評価します。コード例 lhs || rhs
の場合、その逆が真となります。もし lhs
が truthy なら、式は lhs
を評価します。それ以外の場合、式は rhs
を評価します。
JavaScriptでの長いプロパティアクセスチェーンはエラーが発生しやすく、そのどれもがnull
またはundefined
(「ヌリッシュ」値として知られる)に評価される可能性があります。それぞれの手順でプロパティの存在を確認することは、簡単に深く入れ子になったif
文構造やプロパティアクセスチェーンを複製する長いif
条件に変わる可能性があります:
JSON ⊂ ECMAScript 提案により、JSONはECMAScriptの構文的部分集合となりました。これがすでにそうでなかったことに驚いたなら、あなたは一人ではありません!
ES2018では、ECMAScriptの文字列リテラルにはエスケープされていないU+2028 LINE SEPARATORおよびU+2029 PARAGRAPH SEPARATOR文字を含めることができませんでした。これらはそのコンテキストでも行終端子と見なされるためです:
// 未エスケープのU+2028文字を含む文字列。
const LS = '
';
// → ES2018: SyntaxError
// `eval`によって生成された、未エスケープのU+2029文字を含む文字列:
const PS = eval('"\u2029"');
// → ES2018: SyntaxError
これは問題です。なぜなら、JSON文字列にはこれらの文字を含めることができるからです。その結果、開発者はこれらの文字を処理するために、ECMAScriptプログラム内に有効なJSONを埋め込む際に特別な後処理ロジックを実装する必要がありました。このようなロジックがなければ、コードに微妙なバグが発生したり、セキュリティ問題が生じる可能性さえありました!
すでにご存知かもしれませんが、Intl.NumberFormat
APIはモダンな環境でしばらくの間サポートされてきました。
Intl.NumberFormat
の最も基本的な形では、ロケールに対応した数値フォーマットをサポートする再利用可能なフォーマッタインスタンスを作成できます。他のIntl.*Format
APIと同様に、フォーマッタインスタンスはformat
メソッドとformatToParts
メソッドの両方をサポートしています。
もし以前にWebブラウザで使用するJavaScriptを書いたことがあるなら、グローバルthis
にアクセスするためにwindow
を使用した可能性があります。Node.jsでは、global
を使ったことがあるかもしれません。どちらの環境でも動作するコードを書く場合、利用可能なものを検出して使用してきたかもしれませんが、サポートする環境とユースケースの数が増えるごとにチェックすべき識別子のリストは増加します。それはすぐに管理ができなくなります:
一般的に、JavaScriptではオブジェクトへの参照は_強く保持されており_、オブジェクトへの参照がある限り、ガベージコレクションされることはありません。
const ref = { x: 42, y: 51 };
// `ref`(または同じオブジェクトへの他の参照)にアクセスできる限り、
// オブジェクトはガベージコレクションされません。
現在のところ、WeakMap
とWeakSet
はJavaScriptでオブジェクトを弱参照する唯一の方法です:WeakMap
やWeakSet
にキーとしてオブジェクトを追加しても、ガベージコレクションを妨げることはありません。
const wm = new WeakMap();
{
const ref = {};
const metaData = 'foo';
wm.set(ref, metaData);
wm.get(ref);
// → metaData
}
// このブロックスコープ内で`ref`への参照が無くなったため、
// オブジェクトはガベージコレクションされます。
// ただし、それが`wm`のキーである場合でも、`wm`へのアクセスは可能です。
犬の配列を持っているとして、それぞれの犬には名前と評価があります。(これが奇妙な例に聞こえるなら、これを専門としているTwitterアカウントがあることを知っておくと良いでしょう…聞かないでくださいね!)
// 配列が `name` でアルファベット順にソートされている点に注意してください。
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 },
];
// 犬を `rating` の降順でソートします。
// (この操作は `doggos` を直接変更します。)
doggos.sort((a, b) => b.rating - a.rating);
JavaScript の Symbol
は作成時に説明を付けることができます:
const symbol = Symbol('foo');
// ^^^^^
以前は、この説明にプログラム的にアクセスする唯一の方法は Symbol.prototype.toString()
を間接的に使用することでした:
const symbol = Symbol('foo');
// ^^^^^
symbol.toString();
// → 'Symbol(foo)'
// ^^^
symbol.toString().slice(7, -1); // 🤔
// → 'foo'
しかし、このコードは少し魔法のようで自明ではなく、“意図を表現し、実装を示さない”という原則に反しています。また、このテクニックでは説明がないシンボル (例: Symbol()
) と、空の文字列を説明として持つシンボル (例: Symbol('')
) を区別することができません。
Object.fromEntries
は、組み込みの JavaScript ライブラリへの有益な追加機能です。その機能を説明する前に、既存の Object.entries
API を理解することが助けになります。
Object.entries
Object.entries
API はしばらく前から存在しています。
オブジェクト内の各キーと値のペアについて、Object.entries
は配列を返します。その配列の最初の要素がキー、2番目の要素が値です。
for
-of
と組み合わせて使うと、Object.entries
はすべてのキーと値のペアをエレガントにループ処理するための非常に便利な方法を提供します。
const object = { x: 42, y: 50 };
const entries = Object.entries(object);
// → [['x', 42], ['y', 50]]
for (const [key, value] of entries) {
console.log(`The value of ${key} is ${value}.`);
}
// 出力:
// The value of x is 42.
// The value of y is 50.
しかし、これまでのところ、entries の結果から元のオブジェクトに戻す簡単な方法はありませんでした… 今までは!
Object.fromEntries
新しい Object.fromEntries
API は、Object.entries
の逆の動作をします。これにより、エントリを基にオブジェクトを簡単に再構築できるようになります。
const object = { x: 42, y: 50 };
const entries = Object.entries(object);
// → [['x', 42], ['y', 50]]
const result = Object.fromEntries(entries);
// → { x: 42, y: 50 }
一般的な使用例として、オブジェクトの変換があります。これを行うにはエントリをループ処理し、すでにおなじみの配列メソッドを使用します。
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 }
この例では、オブジェクトを filter
してキーの長さが 1
のものだけを取得します。つまり、キー x
と y
のみで、キー abc
は取得しません。その後、残りのエントリを map
して、各キーと値のペアを更新して返します。この例では、各値を 2
倍にして新しい値を得ます。結果として、新しいオブジェクトが得られます。そこには x
と y
のプロパティのみがあります。