ECMAScript(ECMA-262)は、JavaScriptの文法と組み込みオブジェクトを定める標準仕様です。2026年6月に第17版のECMAScript 2026(ES2026)が承認されました。この記事では、JavaScriptとの線引き、版の歴史、TC39の提案ステージ、ES Modules(ESM)とCommonJSの読み込み規則を、一次情報とNode.js 26.5.0での実行結果をもとに整理します。
まとめ:ECMAScriptの定義・最新版・JavaScriptとの線引き
- ECMAScriptはEcma InternationalのTC39が策定する言語仕様で、規格番号はECMA-262。JavaScriptはその仕様をV8やSpiderMonkeyなどのエンジンが実装したものです。
- 最新版は2026年6月の第17版(ES2026)。ES2016(第7版)から年次リリース方式に移り、毎年6月に改訂されています。
- DOMや
fetchはブラウザ側の仕様、requireはNode.jsの機能で、どちらもECMAScriptには含まれません。 - ESMはECMAScriptが定めるモジュール方式(
import・export)です。Node.jsでは拡張子とpackage.jsonのtypeで読み込み方式が決まります。 - 仕様の版に入った機能でも、実行環境で動くとは限りません。Node.js 26.5.0では、ES2026の
Math.sumPreciseがフラグ無しでは使えませんでした。
以下で、それぞれの根拠と、実務で版をどう確かめるかを説明します。
ECMAScriptの定義とJavaScript・ブラウザAPIとの境界
ECMA-262が定める範囲とエンジンによる実装
ECMA-262が定めるのは、変数宣言や関数・クラスなどの構文、ArrayやPromiseなどの組み込みオブジェクト、モジュールの読み込み手順です。策定するのはEcma International内の技術委員会TC39で、仕様書の最新ドラフトはtc39.esで公開されています。
この仕様を実行できる形にしたものがJavaScriptエンジンです。ChromeとNode.jsはV8、FirefoxはSpiderMonkey、SafariはJavaScriptCoreを使います。「ECMAScriptとJavaScriptの違い」は、設計図と実装の関係と捉えると混乱しません。
「JavaScript」という名前自体は商標です。米国特許商標庁の記録では、JAVASCRIPT商標(登録番号2416017)の登録者はOracle America, Inc.です。Deno Land Inc.が2024年11月22日に取消手続(92086835)を申し立てましたが、2026年8月28日付で和解交渉のため手続が停止されています。
DOM・fetch・requireがECMAScriptに含まれない理由
document.querySelectorなどのDOM操作やfetchは、WHATWGが策定するHTML・DOM・Fetchの各仕様に属します。ブラウザが実行環境として追加している機能なので、Node.jsではdocumentが存在しません。
同様にrequireとmodule.exportsはNode.jsが採用したCommonJS方式の機能で、ECMAScriptの仕様には書かれていません。国際化APIのIntlは別規格のECMA-402が定めています。ある機能を調べるとき、どの仕様書に載っているかを先に確かめると、ブラウザとNode.jsで挙動が違う理由が分かります。
ECMAScriptの版の歴史:第1版(1997年)からES2026まで
| 版 | 通称 | 承認時期 | 主な追加 |
|---|---|---|---|
| 第1版 | ES1 | 1997年6月 | 最初の標準化 |
| 第2版 | ES2 | 1998年8月 | ISO規格との整合 |
| 第3版 | ES3 | 1999年12月 | 正規表現・try/catch |
| 第4版 | ES4 | 発行されず | 策定中止 |
| 第5版 | ES5 | 2009年12月 | strict mode・JSON |
| 第5.1版 | ES5.1 | 2011年6月 | ISO規格との整合 |
| 第6版 | ES2015(ES6) | 2015年6月 | let/const・class・モジュール・Promise |
| 第8版 | ES2017 | 2017年6月 | async/await |
| 第11版 | ES2020 | 2020年6月 | BigInt・オプショナルチェーン |
| 第16版 | ES2025 | 2025年6月 | Iteratorヘルパー・Setメソッド |
| 第17版 | ES2026 | 2026年6月 | Array.fromAsync・Error.isError |
承認時期はEcma InternationalのECMA-262ページの版一覧に基づきます。第7版から第15版も毎年6月に承認されており、表では主要な版だけを抜き出しました。
ES4の策定中止とES5までの10年の空白
第3版(1999年12月)から第5版(2009年12月3日のEcma総会で承認)までは10年空いています。第5.1版の仕様書の序文には、第4版の作業は完了せず、第4版として刊行されなかったと記されています。そのため版番号は3の次が5です。第5版ではstrict modeとJSONオブジェクトが加わりました。
ES2016からの年次リリースとStage 4到達順の取り込み
第6版で名称が「ECMAScript 2015」になり、以後は年号で呼ばれます。ES6とES2015は同じ版を指します。第6版にはアロー関数、class、モジュール、Promiseが一度に入り、現在のJavaScriptの書き方の土台になりました。
現行仕様の序文によると、TC39の年次リリース方式と公開された策定プロセスで出た最初の版はES2016です。版に入れる機能を事前にまとめて決めるのではなく、後述のStage 4に到達した提案を順にドラフトへ取り込みます。TC39のプロセス文書では、3月にその年の版を分岐させて以後は編集上の修正だけを受け付け、7月をEcma総会での承認時期としています。実際のES2026は2026年6月30日の第131回Ecma総会で承認されました。1つの機能の議論が長引いても、ほかの機能の収録は止まりません。
ES2025・ES2026で追加された機能と次のES2027
TC39の完了済み提案一覧では、各提案に刊行予定年(Expected Publication Year)が付いています。ES2025にはPromise.try、RegExp.escape、Iteratorヘルパー、Setの集合演算メソッド、Import Attributes、JSON Modules、Float16Arrayなどが入りました。個々の使い方はES2025の新機能まとめで扱っています。
ES2026の収録はArray.fromAsync、Error.isError、Math.sumPrecise、Uint8ArrayのBase64変換、Iteratorの連結(Iterator.concat)、JSON.parseのソーステキスト参照、MapのgetOrInsert(Upsert)の7件です。2026年9月時点で刊行予定年が2027の提案には、日時APIのTemporal、using宣言によるExplicit Resource Management、Joint Iteration、Atomics.pauseがあります。
TC39の提案ステージとStage 4に進む条件
| ステージ | 位置づけ | この段階で求められるもの |
|---|---|---|
| Stage 0 | アイデア | 正式な検討前 |
| Stage 1 | 検討開始 | 解決したい課題の特定 |
| Stage 2 | ドラフト | 解決策の選定と仕様文の草案 |
| Stage 2.7 | 原則承認 | Test262テストの作成 |
| Stage 3 | 実装推奨 | 本番品質の実装からのフィードバック |
| Stage 4 | 完了 | 2つの互換実装と仕様PRの承認 |
TC39のプロセス文書では、Stage 2.7の段階でTest262(公式の適合テスト)を作成し、Stage 4に到達した提案が次の版の仕様に取り込まれると定めています。Stage 4に進む条件は、Test262に合格する2つの互換実装、出荷済み実装での十分な利用実績、統合した仕様文のプルリクエストの提出と編集者グループの承認です。Stage 2.7は2023年11月30日のTC39会合で正式に採用された比較的新しい段階で、それ以前の解説記事にはStage 0から4の5段階として書かれています。
実務で「もう使えるか」を判断する目安はStage 3以降です。プロセス文書はStage 2を「設計はドラフトで、まだ大きく変わり得る」段階としており、この段階の構文をトランスパイラで先取りすると、仕様が変わったときに書き直しが発生します。Stage 3でも、Web互換性や本番品質の実装から問題が見つかれば変更があり得ると明記されています。
ES Modules(ESM)とCommonJSの違いとNode.jsでの読み込み規則
ESMとCommonJSを分ける拡張子とpackage.jsonのtype
ESMはES2015で仕様に入ったモジュール方式で、importとexportで依存を宣言します。CommonJSはECMAScriptにモジュールが無かった時代にNode.jsが採用した方式で、requireとmodule.exportsを使います。
Node.jsは次の順でファイルの方式を判定します。.mjsは常にESM、.cjsは常にCommonJSです。.jsは、最も近いpackage.jsonのtypeがmoduleならESM、commonjsならCommonJSとして扱われます。typeが無い場合の.jsは、CommonJSとして評価するとエラーになる構文を含むとESMとして扱われます(構文検出。v22.7.0とv20.19.0で既定有効)。対象はimport文、export文、import.meta、トップレベルのawait、requireなどCommonJSのラッパー変数の再宣言で、動的なimport()は含みません。この判定には性能上のコストがあるとドキュメントに書かれているため、パッケージを作る場合はtypeを明示します。
ブラウザでは<script type="module">で読み込んだスクリプトがESMになります。Node.jsのESMでは__dirnameが使えないため、代わりにimport.meta.dirnameを使います。
ESMからCommonJSを読む・require(esm)でESMを読む実行例
Node.js 26.5.0で、ESMとCommonJSを相互に読み込めるか確かめたコードです。math.mjsがESM、legacy.cjsがCommonJSです。
// math.mjs
export const add = (a, b) => a + b;
// legacy.cjs
module.exports = { mul: (a, b) => a * b };
// app.mjs(ESMからESMとCommonJSを読む)
import { add } from './math.mjs';
import legacy from './legacy.cjs';
console.log(add(2, 3), legacy.mul(2, 3), typeof require);
// app.cjs(CommonJSからESMを読む)
const { add } = require('./math.mjs');
console.log(add(2, 3));
$ node app.mjs
5 6 undefined
$ node app.cjs
5
ESM側ではrequireがundefinedになり、CommonJSはimport文でそのまま読めます。CommonJSからESMをrequireする機能(require(esm))は、Node.jsのドキュメントによるとv23.0.0、v22.12.0、v20.19.0で--experimental-require-moduleフラグが不要になりました。
トップレベルawaitを含むESMのrequire制限
require(esm)には例外があります。読み込むESMがトップレベルでawaitを使っていると、requireは同期的に値を返せないためエラーになります。
// tla.mjs
export const config = await Promise.resolve({ ok: true });
// app-tla.cjs
const { config } = require('./tla.mjs');
console.log(config);
$ node app-tla.cjs
Error [ERR_REQUIRE_ASYNC_MODULE]: require() cannot be used on an ESM graph with top-level await. Use import() instead.
CommonJSのトップレベルではawaitが使えないため、async関数の中で動的なimport()を使うか、呼び出し側をESMへ移します。
// app-tla-fix.cjs
async function main() {
const { config } = await import('./tla.mjs');
console.log(config);
}
main();
$ node app-tla-fix.cjs
{ ok: true }
ESMとCommonJSの内部構造の違いはNative ESMとCommonJSの違いで詳しく扱っています。
ES2026対応を実行環境で確かめる手順と、版の年号で判断してはいけない場面
Node.js 26.5.0での機能検出の結果
「ES2026に入った」は「手元のランタイムで動く」を意味しません。版は仕様書の年号で、エンジンの実装はそれと別の日程で進みます。次のコードは、ES2025からES2027の代表的な機能が存在するかを判定します。
const checks = {
'ES2025 Promise.try': () => typeof Promise.try === 'function',
'ES2025 RegExp.escape': () => typeof RegExp.escape === 'function',
'ES2026 Error.isError': () => typeof Error.isError === 'function',
'ES2026 Map.prototype.getOrInsert': () => typeof Map.prototype.getOrInsert === 'function',
'ES2026 Math.sumPrecise': () => typeof Math.sumPrecise === 'function',
'ES2027 Temporal': () => typeof globalThis.Temporal === 'object',
};
for (const [name, test] of Object.entries(checks)) {
console.log(`${test() ? 'OK' : 'NG'} ${name}`);
}
$ node check-es.mjs
OK ES2025 Promise.try
OK ES2025 RegExp.escape
OK ES2026 Error.isError
OK ES2026 Map.prototype.getOrInsert
NG ES2026 Math.sumPrecise
OK ES2027 Temporal
$ node --js-sum-precise check-es.mjs
OK ES2025 Promise.try
OK ES2025 RegExp.escape
OK ES2026 Error.isError
OK ES2026 Map.prototype.getOrInsert
OK ES2026 Math.sumPrecise
OK ES2027 Temporal
nodejs.orgの公式バイナリ(Node.js 26.5.0、darwin-x64、V8 14.6)での結果です。ES2026のMath.sumPreciseは既定で無効で、V8の--js-sum-preciseフラグを付けたときだけ使えました。同じES2026でもError.isErrorとgetOrInsertは既定で使えます。ES2027予定のTemporalは、Node.js 26.0.0のリリースノートに既定で有効と書かれているとおり、フラグ無しで存在しました。
同じNode.js 26.5.0でもビルド設定でTemporalの有無が変わる例
Homebrewで入れたNode.js 26.5.0で同じコードを実行すると、TemporalだけがNGになりました。V8のバージョンは公式バイナリと同じ14.6.202.34ですが、ビルド設定のv8_enable_temporal_supportが公式バイナリでは1、このHomebrew版では0でした。
$ node -p "process.config.variables.v8_enable_temporal_support"
1
バージョン番号が同じでも、配布元のビルド設定で使える組み込み機能が変わります。CIや本番コンテナのNode.jsが公式バイナリとは限らないため、手元の結果を本番に当てはめる前に配布元をそろえてください。Node.js 26の変更点全体はNode.js 26の新機能と変更点で扱っています。
本番コードで新しい版の機能を使ってよい条件
判断基準は、仕様の年号ではなく、サポート対象の全実行環境での実測です。ブラウザ向けなら対象ブラウザの最低バージョン、Node.js向けならpackage.jsonのenginesに書いた最低バージョンで、上のような機能検出に加えて、実際に使う引数・戻り値・例外のテストを通してから採用します。Node.jsは本番と同じ配布元のバイナリで確かめます。
V8のフラグで有効化した機能を本番で使うのは避けるべきです。フラグはエンジンの内部設定で、Node.jsのマイナー更新で既定値や名前が変わっても互換性の保証がありません。フラグ付きでしか動かない機能は、ポリフィルで補うか、既定で有効になるバージョンまで待ちます。
よくある質問
ECMAScriptとJavaScriptの違いは何ですか?
ECMAScriptはEcma InternationalのTC39が策定する言語仕様(ECMA-262)で、JavaScriptはその仕様をV8やSpiderMonkeyなどのエンジンが実装したものです。ブラウザのJavaScriptにはDOMやfetch、Node.jsのJavaScriptにはrequireやファイル操作が加わりますが、これらは実行環境が追加した機能で、ECMAScriptの仕様には含まれません。
ESMとは何ですか?
ESMはES Modulesの略で、ES2015でECMAScriptの仕様に入ったモジュール方式です。exportで公開し、importで読み込みます。Node.jsでは.mjsファイル、またはpackage.jsonのtypeがmoduleのパッケージ内の.jsファイルがESMとして扱われます。従来のCommonJS(require)とは読み込み方式が異なります。
CommonJSとECMAScriptの違いは何ですか?
CommonJSはNode.jsが採用したモジュール方式で、ECMAScriptの仕様には含まれません。ECMAScriptが定めるモジュール方式はESMです。Node.jsではv22.12.0とv20.19.0以降、CommonJSからフラグ無しでESMをrequireできますが、トップレベルでawaitを使うESMはERR_REQUIRE_ASYNC_MODULEで失敗します。
ES6とES2015は同じですか?
同じ版を指します。2015年6月に承認された第6版の正式名称がECMAScript 2015で、ES6は版番号による通称です。これ以降は年号で呼ぶのが正式で、年次リリース方式で最初に出たES2016が第7版、最新のES2026が第17版にあたります。
ECMAScriptとTypeScriptの違いは何ですか?
TypeScriptはMicrosoftが開発する言語で、ECMAScriptの構文に型注釈を加えたものです。TypeScriptのコードはコンパイル時に型を取り除いてJavaScriptに変換されるため、ECMAScriptの標準仕様そのものではありません。型の書き方はTypeScriptとは?型・型推論・型注釈の書き分けで解説しています。