UnsplashのGoran Ivosが撮影した写真
ECMAScriptは、JavaScriptの文法、型、標準組み込みオブジェクトなどを定める標準仕様です。開発では、「どの版の構文を前提に書くか」「古い環境向けにトランスパイルやポリフィルが要るか」を判断する土台になります。
ただし、ECMAScriptが定めるのは言語コアです。DOMやFetch APIのようなWeb APIは別仕様に属します。この切り分けを押さえておくと、「JavaScriptの仕様」と「実行環境が提供する機能」を混同しにくくなります。
ECMAScriptの定義、JavaScriptとの関係、主要機能、導入時の考え方までを整理すると、どの仕様を前提にコードを書くべきかを判断しやすくなります。
ECMAScriptとは、Ecma Internationalによって標準化されるスクリプト言語の仕様です。一般には「JavaScriptの仕様」と説明されることが多いですが、より正確には、JavaScriptが準拠して実装する言語コアを定義したものです。対象になるのは、文法、型、標準組み込みオブジェクト、例外処理、モジュール、非同期処理の基本形などです。
ECMAScriptの役割は、同じJavaScriptコードが複数の実行環境でできるだけ一貫して動くように、共通のルールを定めることです。具体的には、次のような要素を標準化します。
let/const、アロー関数、クラス構文などArray、Map、Promise、JSONなど一方、ブラウザのDOM操作(document)やFetch API(fetch)は、ECMAScriptそのものには含まれません。ECMAScriptを理解すると、言語としてのJavaScriptを把握しやすくなりますが、Web開発ではWeb APIを別に理解する必要があります。
JavaScriptは、ECMAScriptを実装した言語の代表例です。開発の現場で「ES2020対応」などと言う場合は、ECMAScriptの特定の版に含まれる機能を、その実行環境で使えるかどうかを指していることが一般的です。
ただし、実行環境によって差が出る点も見落とせません。ブラウザではDOMやWeb APIの対応状況が関わりますし、Node.jsではバージョンによって利用できる構文や標準機能が変わります。そのため、「ECMAScriptの仕様」と「ターゲット環境の実装状況」を分けて確認する視点が欠かせません。
ECMAScriptは1997年の初版以降、改訂を重ねてきました。大きな転機としてよく挙げられるのが、ES2015(通称ES6)です。ここでlet/const、アロー関数、クラス構文、モジュールなどが加わり、その後は年次で仕様が追加される形が定着しました。
開発では「ES2015」「ES2017」「ES2020」のように年で呼ばれることが多く、策定途中を含む新しい仕様群をまとめて「ESNext」と呼ぶこともあります。確認すべきなのは呼び名よりも、自分のターゲット環境で使えるか、使えないなら変換や代替が要るかです。
ECMAScriptの仕様策定はTC39(Technical Committee 39)で進みます。新機能は提案として議論され、段階(stage)を進みながら仕様が固まっていきます。開発者は、この提案ステージを見て、その機能がどの程度固まっているかを判断します。たとえばstage 3は仕様がかなり固まった段階、stage 0は初期提案の段階です。
ECMAScriptを理解すると、読みやすく保守しやすいコードを書きやすくなります。ここでは、差が出やすい論点を中心に整理します。
varは関数スコープで、巻き上げ(hoisting)の影響を受けやすく、意図しない上書きや参照につながることがあります。一方、letとconstはブロックスコープで、変数の有効範囲を限定しやすくなります。
let:再代入する変数に使うconst:再代入しない参照に使う(ただしオブジェクト内部の変更は可能)この使い分けをそろえるだけでも、スコープ起因の不具合を減らしやすくなります。
アロー関数は短く書けるだけでなく、thisの扱いが従来の関数と異なるため、コールバック内での意図しないthis参照を避けやすい場面があります。ただし、アロー関数はコンストラクタとして使えないなどの制約があるため、用途に応じて選びます。
テンプレート文字列(バッククォート)は、文字列結合の可読性を上げ、複数行文字列も自然に表現できます。UI文言、ログ、HTML断片を扱うコードでは差が出やすい機能です。
クラス構文は、プロトタイプベースの仕組みを分かりやすく書くための構文です。継承、コンストラクタ、メソッド定義が整理されるため、チーム開発では読みやすさにつながります。一方で、内部原理としてのプロトタイプチェーンを知っていると、デバッグしやすくなります。
モジュール(import/export)は、依存関係と公開範囲を明確にし、名前衝突を避けやすくします。ブラウザ、Node.js、ビルド環境では扱いが少しずつ異なるため、「どの形式(ESM/CJS)で扱うか」「バンドラーが何を前提にしているか」を含めて設計します。
Promiseは非同期処理を扱う基本単位で、then/catch/finallyによって、コールバックの深い入れ子を避けやすくします。さらにasync/awaitを使うと、Promiseベースの非同期処理を順序立てて読みやすく書けます。
ただし、非同期処理には「待たなくてよい処理まで直列にしてしまう」「例外を握りつぶす」といった落とし穴があります。構文だけでなく、どこを直列にし、どこを並列にするかまで設計する視点が要ります。
ECMAScriptの知識は、新機能の名前を知ることよりも、安全に使う判断ができることに価値があります。とくに次の三点は、導入時に必ず確認しておきたい項目です。
まず決めるべきなのは、どこで動かすかです。ブラウザの対象バージョン、Node.jsの運用バージョン、社内端末の制約などによって、使える構文と標準機能は変わります。ここが曖昧なまま書き始めると、後から手戻りが大きくなります。
古い環境に合わせる手段は大きく二つあります。
Promiseなど)を追加して補うどこまで対応するかは、利用者層、性能、保守性のバランスで決めます。何でも最新仕様で書いて一括変換するより、必要な範囲を見極めたほうが運用しやすくなります。
ECMAScriptは仕様であり、実際に動くかどうかは実行環境の実装に左右されます。さらにWeb開発では、ECMAScriptに加えてWeb API(DOM、Storage、Service Workerなど)の実装状況も関わります。そのため、設計では仕様の理解に加え、互換性と運用要件を踏まえて採用範囲を決めます。
ECMAScriptは、JavaScriptの言語コアを定める標準仕様です。文法や標準組み込みを理解する土台になり、保守しやすいコードを書くうえでも外せません。
確認すべきなのは、新機能の数ではなく、ターゲット環境を踏まえてどの仕様を前提にするかです。トランスパイルやポリフィルの要否、Web APIとの切り分け、実行環境ごとの差を押さえておくと、設計と運用の判断をそろえやすくなります。
同じではありません。ECMAScriptは言語仕様で、JavaScriptはその仕様を実装した言語です。
定義しません。DOMやfetchなどのWeb APIは、ECMAScriptとは別の仕様群で標準化されます。
同じ版を指します。ES6は通称で、正式にはES2015(2015年版)です。
ターゲット環境の対応状況によります。必要に応じてトランスパイルやポリフィルを併用します。
トランスパイルは新しい構文を古い構文へ変換し、ポリフィルは新しい標準機能を追加して補います。
新機能提案の成熟度を示す段階です。段階が進むほど仕様が固まり、採用判断をしやすくなります。
同じではありません。どちらも実装の進み方が異なるため、利用可否は個別に確認します。
大規模開発では有力な選択肢です。運用環境に合わせてESM/CJSやビルド方針を決めて導入します。
非同期処理の手順や例外処理を読みやすく整理したい場面で役立ちます。Promiseを前提に設計しておくと扱いやすくなります。
言語コアと実行環境差(ブラウザ/Node.js)を切り分け、対応範囲と互換性の考え方から押さえると理解しやすくなります。