JavaScriptは毎年新しい仕様が追加されています。
古い書き方のまま開発を続けていると、以下のような場面で非効率なコードを書いてしまうことがあります。
- 配列の末尾要素を取得する際に
arr[arr.length - 1]と書いている - 配列をソートするたびに元のデータが書き換わってしまう
- 配列をカテゴリごとにグループ分けするのに複雑な処理を書いている
ES2022〜ES2024で追加された機能を使うことで、こういった処理をシンプルに書くことができます。
実践
at() ― 配列・文字列の末尾要素を取得する
以下のような配列があるとします。
const arr = [10, 20, 30, 40, 50];
at() を使うと末尾からの要素取得をシンプルに書けます。
console.log(arr.at(-1)); // 50 console.log(arr.at(-2)); // 40
従来の書き方と比較すると以下のようになります。
// 従来の書き方 console.log(arr[arr.length - 1]); // 50 // at() を使った書き方 console.log(arr.at(-1)); // 50
toSorted() / toReversed() ― 元の配列を変えずに操作する
以下のような配列があるとします。
const original = [3, 1, 4, 1, 5];
従来の sort() は元の配列を書き換えてしまいます。
// 従来の書き方(元の配列が変わってしまう) const sorted = original.sort(); console.log(sorted); // [1, 1, 3, 4, 5] console.log(original); // [1, 1, 3, 4, 5] ← 書き換わっている
toSorted() を使うと元の配列を保ったまま操作できます。
// toSorted() を使った書き方 const sorted = original.toSorted(); console.log(sorted); // [1, 1, 3, 4, 5] console.log(original); // [3, 1, 4, 1, 5] ← 変化なし
同様に toReversed() で元の配列を変えずに逆順にできます。
const reversed = original.toReversed(); console.log(reversed); // [5, 1, 4, 1, 3] console.log(original); // [3, 1, 4, 1, 5] ← 変化なし
Object.groupBy() ― 配列をグループ分けする
以下のような配列があるとします。
const products = [
{ name: "りんご", category: "果物" },
{ name: "バナナ", category: "果物" },
{ name: "にんじん", category: "野菜" },
{ name: "キャベツ", category: "野菜" },
];
Object.groupBy() を使うと、指定したキーでグループ分けした結果を取得できます。
const grouped = Object.groupBy(products, item => item.category);
console.log(grouped);
// {
// 果物: [{ name: "りんご", ... }, { name: "バナナ", ... }],
// 野菜: [{ name: "にんじん", ... }, { name: "キャベツ", ... }]
// }
従来はこれを実現するために reduce() を使った複雑な処理が必要でした。
// 従来の書き方
const grouped = products.reduce((acc, item) => {
const key = item.category;
if (!acc[key]) acc[key] = [];
acc[key].push(item);
return acc;
}, {});
グループ化後のキー・値の取得
Object.groupBy() の結果は通常のオブジェクトなので、Object.keys() などがそのまま使えます。
// キーだけ取得
console.log(Object.keys(grouped)); // ["果物", "野菜"]
// 値だけ取得
console.log(Object.values(grouped)); // [[{...}, {...}], [{...}, {...}]]
// キーと値をセットで取得
console.log(Object.entries(grouped));
// [["果物", [{...}, {...}]], ["野菜", [{...}, {...}]]]
| メソッド | 取得できるもの |
|---|---|
Object.keys(grouped) | キーの配列 |
Object.values(grouped) | 値(グループごとの配列)の配列 |
Object.entries(grouped) | [キー, 値] のペアの配列 |
with() ― 特定の要素だけ変えた新しい配列を返す
with(インデックス, 新しい値) で、指定した位置の値だけを変えた新しい配列を返します。
const arr = ["a", "b", "c", "d", "e"]; const newArr = arr.with(2, "X"); console.log(newArr); // ["a", "b", "X", "d", "e"] console.log(arr); // ["a", "b", "c", "d", "e"] ← 元は変わらない
負のインデックスも使えます。
const newArr = arr.with(-1, "Z"); console.log(newArr); // ["a", "b", "c", "d", "Z"]
オブジェクトの配列で1件だけ更新したい場合によく使います。
const users = [
{ id: 1, name: "田中", active: true },
{ id: 2, name: "鈴木", active: true },
{ id: 3, name: "佐藤", active: true },
];
const index = users.findIndex(u => u.id === 2);
const updated = users.with(index, { ...users[index], active: false });
console.log(updated);
// [
// { id: 1, name: "田中", active: true },
// { id: 2, name: "鈴木", active: false }, ← ここだけ変わっている
// { id: 3, name: "佐藤", active: true },
// ]
console.log(users); // 元の配列は変わらない
Vue.jsのwatcherとの組み合わせ
非破壊的メソッドの返り値を元の変数に代入することで、Vue.jsのwatcherが変更を検知できます。
// ❌ 代入なし → watcherは検知できない
this.users.with(index, { ...this.users[index], active: false });
// ✅ 代入あり → watcherが検知できる
this.users = this.users.with(index, { ...this.users[index], active: false });
| 操作 | watcherが検知できるか | deep: trueが必要か |
|---|---|---|
this.users = this.users.with(...) (代入あり) | ✅ 検知できる | 不要 |
this.users.with(...) (代入なし) | ❌ 検知できない | - |
this.users[1].active = false (直接変更) | ✅ 検知できる | 必要 |
解説
at() について
at() は配列・文字列・TypedArrayで使えるメソッドです。
引数に 負の数 を渡すことで、末尾からの位置を指定できます。
at(-1)→ 末尾から1番目(最後の要素)at(-2)→ 末尾から2番目at(0)→ 先頭の要素(通常のarr[0]と同じ)
→ ES2022で追加されました。
toSorted() / toReversed() / toSpliced() / with() について
これらは配列を 非破壊的に操作する ためのメソッドです。
| メソッド | 説明 |
|---|---|
toSorted() | ソートした新しい配列を返す |
toReversed() | 逆順にした新しい配列を返す |
toSpliced() | 要素を追加・削除した新しい配列を返す |
with(index, value) | 特定インデックスの値を変えた新しい配列を返す |
いずれも 元の配列は変更されません。
→ ES2023で追加されました。
Object.groupBy() について
Object.groupBy(配列, グループを返す関数) という形式で使います。
第2引数に渡した関数の 戻り値 がグループのキーになります。
// 数値の偶数・奇数でグループ分けする例
const numbers = [1, 2, 3, 4, 5, 6];
const grouped = Object.groupBy(numbers, n => n % 2 === 0 ? "偶数" : "奇数");
console.log(grouped);
// { 奇数: [1, 3, 5], 偶数: [2, 4, 6] }
→ ES2024で追加されました。
各機能のChrome対応状況
最新のChromeであれば特別な準備なしにそのまま動きます。Chromeのデベロッパーツール(F12)→ Consoleタブで試すことができます。
| 機能 | Chrome対応バージョン | 現在のChromeで動くか |
|---|---|---|
at() | Chrome 92〜 | ✅ |
toSorted() / toReversed() | Chrome 110〜 | ✅ |
Object.groupBy() | Chrome 117〜 | ✅ |
with() | Chrome 110〜 | ✅ |
古いブラウザ対応が必要な場合や古いNode.js環境ではBabelやPolyfillが必要になる場合があります。
まとめ
今回は、ES2022〜ES2024で追加されたモダンJavaScriptの新機能について解説しました。
特に toSorted() / toReversed() / with() などの非破壊的メソッドは、意図しない配列の書き換えによるバグを防ぐことができます。Vue.jsなどのフレームワークとの相性も良く、積極的に活用してみてください。
※ただし、これらの機能は比較的新しいため、古いブラウザや古いNode.jsのバージョンでは動作しない場合があります。使用する環境のバージョンを事前に確認するようにしましょう。

コメント