プログラミング
2026年のJavaScriptについて知っておくべきこと
What to Know About JavaScript in 2026 (blog.master.dev)
要約
この記事は、2026年版としてJavaScriptの最新動向を解説しています。ECMAScript 2025で導入されたイテレータヘルパー、セットメソッド、RegExp.escape()、Promise.try()、インポート属性などの新機能に焦点を当て、それらが開発者のコーディング効率やパフォーマンスにどのように貢献するかを具体例を交えて説明しています。また、JavaScriptのエコシステム全体、ランタイム、フレームワーク、ライブラリ、ツールなども含めた包括的な視点を提供しています。
全文翻訳
JavaScript 2026年に知っておくべきこと
CSSに関する同様の記事を作成しましたが、JavaScriptも同じくらい注目されるべきです!特にJavaScriptはバージョン管理をよりうまく行うようになっているためです。言語自体の新機能について説明しますが、JavaScriptの実践者は言語だけでなく、ランタイム、フレームワーク、ライブラリ、ツールにも及ぶ以上のことを行う必要があります。もう始めましょう、おそらくあなたはすでにスクロールダウンしているでしょうから。
言語の新機能
JavaScriptには年次リリースがあり、私に言わせればこれは非常に良いやり方です!
ECMAScript 2025
最新はECMAScript 2025で、2025年6月に出版され、そのバージョンの仕様全体が利用可能です。
イテレータヘルパー
イテレータに、遅延評価される.map()、.filter()、.take()、.drop()のようなメソッドが直接追加されました。正直なところ、私のような主にフロントエンド開発者にとっては、これは少し難解に感じられます。配列のmap処理はすでにできますから、何がそんなにすごいのか?しかし、パフォーマンスの側面は理解しています。それがここでの一つの側面です。
const result = array
.map(x => x * 2) // メモリ内に新しい配列を作成
.filter(x => x > 10) // ...再び
.slice(0, 3);
// ...再び
これは「遅い」し、「メモリを大量に消費する」方法です。特に配列が非常に大きく、行っている処理が「コストがかかる」場合です。新しいおしゃれな方法は以下のようになります。
const result = Iterator.from(array)
.map(x => x * 2)
.filter(x => x > 10)
.take(3)
.toArray(); // 新しい配列は作成されず、3つ計算されたら停止
そして良いボーナスとして、Iterator.from()全体はiterableなものであれば何でも機能します。つまり、配列だけでなく、セット、マップ、ジェネレータなども対象となり、それらすべてが同じ便利な関数のセットを使用できるようになります。
セットメソッド
JavaScriptにおけるセットは、各アイテムが一意であることが保証されている配列のようなもので、なかなか便利です。それは新しいことではありませんが、2つのセットがある場合、それらの間の重複や非重複などを返すメソッドが利用できるようになりました。
const youKnow = new Set(["JS", "Python", "CSS", "SQL"]);
const jobNeeds = new Set(["JS", "TypeScript", "Python"]);
// あなたがすでに持っている、仕事で必要とされるスキル
youKnow.intersection(jobNeeds); // → Set {"JS", "Python"}
// 全てを組み合わせたもの — あなたのフルスタック + 仕事のニーズ
youKnow.union(jobNeeds); // → Set {"JS", "Python", "CSS", "SQL", "TypeScript"}
// 仕事で必要とされるが、あなたがまだ知らないもの(スキルのギャップ)
jobNeeds.difference(youKnow); // → Set {"TypeScript"}
// あなたが持っているが、仕事では必要とされないスキル
youKnow.difference(jobNeeds); // → Set {"CSS", "SQL"}
// どちらのセットにも現れないスキル
youKnow.symmetricDifference(jobNeeds); // → Set {"CSS", "SQL", "TypeScript"}
// 仕事の要件はすべて、あなたが知っていることの部分集合ですか?
jobNeeds.isSubsetOf(youKnow); // → false
// すべてのスキルを持っていて、さらにそれ以上持っていますか?
youKnow.isSupersetOf(jobNeeds); // → false
// あなたと仕事の間には全く重複がありませんか?
youKnow.isDisjointFrom(jobNeeds); // → false
これは非常に便利だと思います。Claude Codeは、それからインタラクティブなデモを作成するのに楽しんでいました。
RegExのアップデート
状況を説明しましょう。あなたはページ内検索機能を構築しており、ユーザーは独自の検索語を入力します。そして、それを正規表現(RegEx)検索として実装したいとします。そこには危険が伴います。ユーザーが入力する一部の文字は、正規表現では「特殊」文字である可能性があるからです。例えば、$は最後の文字にマッチするなどです。したがって、ユーザーが$9を検索し、それを正規表現にそのまま投入すると、壊れてしまいます。修正するために「エスケープ」する必要がある文字は、手元の正規表現の実装に固有です。そこで!15年間の旅を経て、RegExp.escape()が登場しました。
const query = userInput; // 例: "$5.00 (off!)"
// ❌ BEFORE — 正規表現の特殊文字があると壊れる
const badRe = new RegExp(query, "g");
// ✅ ES2025 — 1つのメソッドで問題解決
const goodRe = new RegExp(RegExp.escape(query), "g");
ここでも、Claude Codeは非常に良いデモを作成してくれました。
正規表現内でフラグがどのように機能するかについてのアップデートもありました。非常に一般的なのは「i」フラグ、つまり大文字小文字を区別しないことを意味するフラグだと思います。したがって、/iで終わる正規表現があった場合、全体が大文字小文字を区別しないことになります。しかし、正規表現の一部だけを大文字小文字を区別しないようにしたい場合はどうでしょうか? now you can wrap parts of it in parentheses and add those flags at the beginning.
// Old way — you couldn't mix case sensitivity
/[a-z]+@[A-Z]+/i // 'i' flag applies to EVERYTHING
// ES2025 — inline modifiers per-group
/(?i:[a-z.]+)@(?-i:[A-Z]+)\.(?i:com|org)/ //^^^^ case-insensitive part
// ^^^^^ case-SENSITIVE part
// ^^^ case-insensitive part
Promiseのアップデート
皆が好きな非同期プログラミングのフローモデル(Promises)に、エラーハンドリングを簡素化できるPromise.try()というアップデートが少しあります。関数は同期または非同期でエラーを発生させる可能性があり、それらを別々に処理する必要がありましたが、今ではまとめて処理できます。
// 非同期かもしれないし、同期的にスローするかもしれない関数
function loadUser(id) {
if (!id) throw new Error("No ID"); // sync throw
return fetch(`/api/users/${id}`); // async
}
// ❌ BEFORE — 2つの別々のエラーパス
let p;
try {
p = loadUser(id); // catch sync throw here…
} catch (e) {
handleError(e);
}
p?.catch(e => handleError(e)); // …and async reject here
// ✅ ES2025 — ワンライナー、1つの.catch()
Promise.try(() => loadUser(id))
.then(user => render(user))
.catch(err => showError(err)); // BOTHをキャッチ
ここでも、Claude Codeが作成したデモを参照します。これは概念を実証するのに驚くほど良い仕事をしています。
インポート属性
インポート属性は個人的に大好きな機能です。本当に!まず、JSONデータを取得してパースするなどの手間なしに、JSONデータとしてインポートできるというアイデアが好きです。
import data from "./file.json" with { type: 'json' }
with の部分とその後のオブジェクトは「インポート属性」と呼ばれ、さらにいくつかのトリックがあります。JSONインポートは私にはきれいに見え、コードを1〜2行節約できますが、正直なところ、Jake ArchibaldがImporting vs fetching JSONで指摘しているように、いくつかの顕著な欠点があります。大きな欠点の一つは、「インポートが失敗すると、モジュールのグラフ全体がダウンしてしまう」ことです。これは非常に悪いことです。失敗をキャッチするために動的import()を使用することもできます。
try {
const { default: data } = await import(url, { with: { type: 'json' }, });
} catch (error) {
// Fallback logic
}
しかし、これは単にJSONを取得した場合に得られるデータほど良くはないため、まだ少し微妙です。Jakeは、インポートされたデータは「ページの存続期間中、モジュールグラフ内に存在し続ける」と述べており、取得後のデータのようにガベージコレクションされるわけではありません。とにかく、慎重に扱いましょう。
JSONだけがインポート属性でインポートできるものではありません。インポート属性が個人的に好きな機能だと言ったのは、主にこの方法でCSSをインポートできることに興奮しているからです。
import componentStyles from "./component.css" with { type: "css" };
これは、WebコンポーネントとCSSモジュールスクリプトを使用したNice Vanilla App Architectureの記事で詳しく説明しています。CSSをJavaScriptコンポーネントのすぐ隣のフォルダに配置できるCSSファイルに保てるという点が、本当に気に入っています。
import sheet from './styles.css' with { type: 'css' };
class MyComponent extends HTMLElement {
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.adoptedStyleSheets = [sheet];
}
...
}
これはES2025のすべてではありません。他にも多くの記事があり、それらに特化して詳しく説明しています。Matthew TysonのInfoWorldの記事「ECMAScript 2025: The best new features in JavaScript」は非常に役立ちました。そこにはFloat16Arrayに関する情報も含まれています。