メインコンテンツまでスキップ

「io19」タグの記事が13件件あります

全てのタグを見る

`Intl.NumberFormat`について

· 約5分
Mathias Bynens([@mathias](https://twitter.com/mathias))とShane F. Carr

すでにご存知かもしれませんが、Intl.NumberFormat APIはモダンな環境でしばらくの間サポートされてきました。

Intl.NumberFormatの最も基本的な形では、ロケールに対応した数値フォーマットをサポートする再利用可能なフォーマッタインスタンスを作成できます。他のIntl.*Format APIと同様に、フォーマッタインスタンスはformatメソッドとformatToPartsメソッドの両方をサポートしています。

globalThis

· 約2分
Mathias Bynens ([@mathias](https://twitter.com/mathias))

もし以前にWebブラウザで使用するJavaScriptを書いたことがあるなら、グローバルthisにアクセスするためにwindowを使用した可能性があります。Node.jsでは、globalを使ったことがあるかもしれません。どちらの環境でも動作するコードを書く場合、利用可能なものを検出して使用してきたかもしれませんが、サポートする環境とユースケースの数が増えるごとにチェックすべき識別子のリストは増加します。それはすぐに管理ができなくなります:

弱い参照とファイナライザ

· 約13分
Sathya Gunasekaran ([@_gsathya](https://twitter.com/_gsathya)), Mathias Bynens ([@mathias](https://twitter.com/mathias)), Shu-yu Guo ([@_shu](https://twitter.com/_shu)), and Leszek Swirski ([@leszekswirski](https://twitter.com/leszekswirski))

一般的に、JavaScriptではオブジェクトへの参照は_強く保持されており_、オブジェクトへの参照がある限り、ガベージコレクションされることはありません。

const ref = { x: 42, y: 51 };
// `ref`(または同じオブジェクトへの他の参照)にアクセスできる限り、
// オブジェクトはガベージコレクションされません。

現在のところ、WeakMapWeakSetはJavaScriptでオブジェクトを弱参照する唯一の方法です:WeakMapWeakSetにキーとしてオブジェクトを追加しても、ガベージコレクションを妨げることはありません。

const wm = new WeakMap();
{
const ref = {};
const metaData = 'foo';
wm.set(ref, metaData);
wm.get(ref);
// → metaData
}
// このブロックスコープ内で`ref`への参照が無くなったため、
// オブジェクトはガベージコレクションされます。
// ただし、それが`wm`のキーである場合でも、`wm`へのアクセスは可能です。

安定した `Array.prototype.sort`

· 約4分
Mathias Bynens ([@mathias](https://twitter.com/mathias))

犬の配列を持っているとして、それぞれの犬には名前と評価があります。(これが奇妙な例に聞こえるなら、これを専門としている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);

`Object.fromEntries`

· 約5分
Mathias Bynens ([@mathias](https://twitter.com/mathias)), JavaScript ウィスパラー

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 のものだけを取得します。つまり、キー xy のみで、キー abc は取得しません。その後、残りのエントリを map して、各キーと値のペアを更新して返します。この例では、各値を 2 倍にして新しい値を得ます。結果として、新しいオブジェクトが得られます。そこには xy のプロパティのみがあります。

Promiseの組み合わせ

· 約5分
Mathias Bynens ([@mathias](https://twitter.com/mathias))

ES2015でPromiseが導入されて以来、JavaScriptでは静的メソッドPromise.allPromise.raceの2つのPromiseコンビネーターがサポートされています。

現在、標準化プロセスを進行中の2つの新しい提案があります: Promise.allSettledPromise.anyです。この追加により、JavaScriptには合計4つのPromiseコンビネーターが存在し、それぞれ異なるユースケースを可能にします。

`Array.prototype.flat` と `Array.prototype.flatMap`

· 約2分
Mathias Bynens ([@mathias](https://twitter.com/mathias))

Array.prototype.flat

この例の配列はいくつかのレベルでネストされています。配列の中にさらに配列があり、その中にも別の配列が含まれます。

const array = [1, [2, [3]]];
// ^^^^^^^^^^^^^ 外側の配列
// ^^^^^^^^ 内側の配列
// ^^^ 最内の配列

Array#flat は指定された配列のフラット化されたバージョンを返します。

array.flat();
// → [1, 2, [3]]

// …は以下と同じです:
array.flat(1);
// → [1, 2, [3]]

デフォルトの深さは 1 です。ただし、任意の数値を渡して、その深さまで再帰的にフラット化できます。結果にネストされた配列が含まれなくなるまで再帰的にフラット化するには、Infinity を渡します。

// 配列にネストされた配列がなくなるまで再帰的にフラット化:
array.flat(Infinity);
// → [1, 2, 3]

このメソッドが Array.prototype.flat と呼ばれる理由で、なぜ Array.prototype.flatten ではないのかについては、こちらをお読みください: #SmooshGate の詳細を確認!

Array.prototype.flatMap

もうひとつの例を見てみます。duplicate という関数は引数に値を取り、その値を2回含む配列を返します。この関数を配列のそれぞれの値に適用すると、ネストされた配列が得られます。

const duplicate = (x) => [x, x];

[2, 3, 4].map(duplicate);
// → [[2, 2], [3, 3], [4, 4]]

その後、結果に対して flat を呼び出して配列をフラット化することができます:

[2, 3, 4].map(duplicate).flat(); // 🐌
// → [2, 2, 3, 3, 4, 4]

このパターンが関数型プログラミングで非常に一般的なので、専用の flatMap メソッドが登場しました。

[2, 3, 4].flatMap(duplicate); // 🚀
// → [2, 2, 3, 3, 4, 4]

flatMapmap を実行し、その後別途 flat を実行するよりもわずかに効率的です。

flatMap の使用例について興味がありますか? Axel Rauschmayer の解説をチェックしてください

Array#{flat,flatMap} のサポート

数値区切り文字

· 約2分
Mathias Bynens ([@mathias](https://twitter.com/mathias))

大きな数値リテラルは、特に繰り返しの数字が多い場合、人間の目で素早く解析するのが困難です。

1000000000000
1019436871.42

可読性を向上させるために、新しいJavaScriptの言語機能で数値リテラルにアンダースコアを区切り文字として使用できるようになりました。その結果、上記のような数値が千単位ごとにグループ化して書き直すことができます。

`String.prototype.matchAll`

· 約3分
Mathias Bynens ([@mathias](https://twitter.com/mathias))

文字列に対して同じ正規表現を繰り返し適用し、すべての一致を取得することは一般的です。ある程度、String#matchメソッドを使用することでこれを今日行うことは可能です。

この例では、16進数の数字のみで構成されたすべての単語を見つけ、それぞれの一致をログに記録します:

const string = 'Magic hex numbers: DEADBEEF CAFE';
const regex = /\b\p{ASCII_Hex_Digit}+\b/gu;
for (const match of string.match(regex)) {
console.log(match);
}

// 出力:
//
// 'DEADBEEF'
// 'CAFE'

しかし、これでは一致する_サブ文字列_しか得られません。通常、サブ文字列だけではなく、各サブ文字列のインデックスや各一致内のキャプチャグループなどの追加情報も必要です。

独自のループを書き、マッチオブジェクトを自分自身で追跡することでこれを達成することはすでに可能ですが、それは少し面倒であまり便利ではありません:

const string = 'Magic hex numbers: DEADBEEF CAFE';
const regex = /\b\p{ASCII_Hex_Digit}+\b/gu;
let match;
while (match = regex.exec(string)) {
console.log(match);
}

// 出力:
//
// [ 'DEADBEEF', index: 19, input: 'Magic hex numbers: DEADBEEF CAFE' ]
// [ 'CAFE', index: 28, input: 'Magic hex numbers: DEADBEEF CAFE' ]

新しいString#matchAllAPIにより、これまでよりも簡単になりました: シンプルなfor-ofループを書くことで、すべてのマッチオブジェクトを取得できます。

const string = 'Magic hex numbers: DEADBEEF CAFE';
const regex = /\b\p{ASCII_Hex_Digit}+\b/gu;
for (const match of string.matchAll(regex)) {
console.log(match);
}

// 出力:
//
// [ 'DEADBEEF', index: 19, input: 'Magic hex numbers: DEADBEEF CAFE' ]
// [ 'CAFE', index: 28, input: 'Magic hex numbers: DEADBEEF CAFE' ]

String#matchAllは特にキャプチャグループを持つ正規表現に役立ちます。個々の一致ごとの完全な情報を、キャプチャグループを含めて提供します。

const string = 'Favorite GitHub repos: tc39/ecma262 v8/v8.dev';
const regex = /\b(?<owner>[a-z0-9]+)\/(?<repo>[a-z0-9\.]+)\b/g;
for (const match of string.matchAll(regex)) {
console.log(`${match[0]} at ${match.index} with '${match.input}'`);
console.log(`→ owner: ${match.groups.owner}`);
console.log(`→ repo: ${match.groups.repo}`);
}

`Intl.ListFormat`

· 約4分
Mathias Bynens([@mathias](https://twitter.com/mathias))およびFrank Yung-Fong Tang

モダンなWebアプリケーションでは、動的なデータで構成されたリストがよく使用されます。例えば、写真ビューアアプリでは以下のような表示がされることがあります:

この写真にはAda、Edith、_および_Graceが含まれます。

テキストベースのゲームでは、異なる種類のリストが用いられるかもしれません:

あなたの超能力を選んでください:不可視化、念動力、_または_共感力

各言語ごとにリストのフォーマットの慣例や単語が異なるため、ローカライズされたリストフォーマッタを実装するのは簡単ではありません。サポートしたいすべての言語の単語(上記の例では「and」や「or」など)のリストが必要なだけでなく、それらの言語における特定のフォーマットの慣例もすべてエンコードする必要があります。Unicode CLDRはそのデータを提供していますが、それをJavaScriptで使用するには、他のライブラリコードと一緒に埋め込んで配送する必要があります。このため、そのようなライブラリの場合、バンドルサイズが増加し、読み込み時間、解析/コンパイルコスト、メモリ使用量に悪影響を及ぼします。