JavaScript の歴史と特徴
第一弾では、まず JavaScript を理解するための背景として、JavaScript の歴史、JavaScript の仕様と特徴、JavaScript 実行エンジンと実行環境について説明します。
- JavaScript の歴史
- JavaScript の仕様と特徴
- JavaScript 実行エンジンと実行環境
- JavaScript 実行モデル
JavaScript の歴史
JavaScript は、1995 年に登場したプログラミング言語です。
当時は、まだ Web ページが静的なものであり、ブラウザで読み込まれた後に動的に内容を変えることができなかった時代でした。
当時ブラウザを提供していた、Netscape 社は非エンジニアが動的な Web ページを作成できるようにするため、JavaScript を開発しました。
JavaScript は、当初はブラウザのためのスクリプト言語として開発されました。
しかし、JavaScript の普及に伴い、Node.js などのブラウザ以外の環境でも使用されるようになり、現在では多くのプラットフォームで利用されています。
JavaScript の仕様と特徴
JavaScript の仕様は、ECMAScript という標準化団体が定めています。
そして、JavaScript の特徴の一つとして、さまざまな環境で実行される可能性があることです。
上述した通り、もともと JavaScript はブラウザ上で実行されることを前提に開発されました。
しかし、ブラウザといっても、Google Chrome や Safari などのブラウザがあり、それぞれのブラウザを作っている組織、団体は異なります。
また近年では Node.js などのサーバーサイドでも実行されるようになり、JavaScript の実行環境は多岐に渡っています。
今後、本記事で、ブラウザ上で実行される JavaScript を中心に学んでいきます。
上述の通り、 JavaScript の仕様を決めているのが ECMAScript です。
しかしややこしいポイントとして、JavaScript とは別に WHATWG (Web Hypertext Application Technology Working Group) という団体がブラウザの実装標準を定めています。JavaScript はブラウザ上で実行されるため、WHATWG が定める標準仕様は JavaScript の仕様とも関連しています。
ECMAScript が定める JavaScript の 標準仕様
ECMAScript® 2026 Language Specification
WHATWG が定めるブラウザの標準仕様
HTML Living Standard
そしてこれらの仕様を、実際に実現しているのが、JavaScript の実行エンジンとブラウザになります。
ややこしくなってきたので、表にまとめてみます。
項目 | 役割 / 責任範囲 |
---|---|
ECMAScript | - JavaScript 言語の仕様を定義(文法、型システム、制御構造、標準ライブラリなど) - 言語の基本的な動作(演算、制御フロー、オブジェクト操作など) - 同期的な処理の定義( for ループ、関数呼び出し、例外処理など)- 非同期処理の一部( Promise 、async/await )の動作も規定 |
WHATWG | - ウェブブラウザの仕様を定義 - DOM API、Fetch API などの仕様を規定- 同期、非同期問わず、タスクをどのように管理、実行するかを仕様レベルで規定 |
JavaScript エンジン | - ECMAScript 仕様に従い、JavaScript コードを解釈・実行するコンポーネント - JavaScript のコードを解釈し、最適化し外部コンポーネントからの指示に応じて実行する |
ブラウザ | - WHATWG の仕様に従い、Web ページをレンダリングする。 - DOM の管理、UI の更新、ネットワーク操作の実行(HTTP リクエストなど) - ユーザー入力イベントや画面描画、その他様々なタスクを管理、実行するシステムを実装 - JavaScript エンジンを搭載し、JavaScript を実行する環境も提供 |
ここで大事なのは、JavaScript 自体の仕様は、ECMAScript で定義されているのですが、その実行環境としてのブラウザの仕様は別の団体である WHATWG で定義されているということです。ECMAScript は概念レベルで仕様を定義している部分も多く、HTML Living Standard は、その概念を維持しつつ、セキュリティや他コンポーネントとの組み合わせなどを加味し、より現実の実装に近い仕様を定義しています。
JavaScript 実行エンジンと実行環境の紹介
上記で説明したように、JavaScript を実行する役割として大きく、実行エンジンと実行環境があります。
JavaScript の実行エンジンは、JavaScript のコードを実行するためのエンジンです。実際のコードをパース、アセンブリ、実行する役割を担います。
一方で、実行環境は JavaScript の実行環境を提供するものです。
例えば、ブラウザや Node.js などが JavaScript の実行環境です。これらの実行環境は 各環境が別々の JavaScript 実行エンジンを搭載しており、また API などの提供も各環境で行っています。
JavaScript の挙動を理解する上で、実行エンジンが提供する挙動と、実行環境が提供する挙動を分けて理解することが重要です。
JavaScript の実行エンジンは、以下のようなものがあります。
- V8 (Chrome, Node.js)
- SpiderMonkey (Firefox)
- JavaScriptCore (Safari)
- JScript (IE)
また実行環境については以下のようなものがあります。
- ブラウザ
- Chrome
- Firefox
- Safari
- Edge
- Node.js
ブラウザや実行エンジンには、バージョンがあり、仕様がアップデートされたりバグが見つかったりすると、順次新しいバージョンが出ていきます。
たまに、古いブラウザに合わせるために、JavaScript で古い書き方をする。ということがありますがこれは、
(1) ECMAScript の新しい仕様が古いブラウザバージョンの JavaScript 実行エンジンでは実現不可能 (互換性や機能の制限)
(2) 各ブラウザによって新しい仕様を反映するタイミングが異なる (ブラウザ側での対応タイミング)
(3) ブラウザのバージョンアップデートタイミングはユーザーによって異なる (ユーザー側での対応タイミング)
などの理由のためです。
これに対応するために用意されているのが、Babel などのトランスパイラです。トランスパイラは、コードを古い書き方に変換して、古いブラウザでも実行できるようにするためのツールです。
余談ですが以下のサイトでは、JavaScript の API について各ブラウザが対応しているかどうかを確認できます。
https://caniuse.com/
JavaScript 実行モデル
最後に、概念レベルで JavaScript がどのように実行されているかを簡単に説明します。詳細はまた次回の記事で解説しようと思います。ここでの説明は基本的な概念を理解するためのものです。
実際の実装詳細は、各ブラウザや実行エンジンによって異なりますが、仕様として決まっている基本的な挙動を理解するためのものです。
まず基本的な用語だけ少し説明します。
JavaScript の実行モデルとしてまず agent
が定義されています。
agent
は概念レベルでの JavaScript の実行モデルであり、シングルスレッドで実行する必要があるとされています。シングルスレッドの制限は、ブラウザ上で同期的に実行される JavaScript の実行モデルであるためです。
ECMAScript ではagent
には、複数の globals
, realm
が含まれており、同期的に相互アクセスを可能とするとしています。しかし、実際的には、セキュリティ上の理由などから、Web ブラウザでは、same-origin policy
によって追加の制約をしています。
realm
は、globals
の集合体であり、globals
は realm
の中に含まれています。 realm
は直訳すると"王国"であり、JavaScript の実行環境のオブジェクトのグループとして定義されています。
そして JavaScriptの実行単位として、Exexution Context
というものがあり
Heap
, Stack
, Queue
という 3 つの主要概念によって実行されます。
...1 回読んで意味がわかった方は天才だと思います。
自分は、この概念を理解するのに様々な文献や仕様を読んで 1 週間ほどかかりました。
まずはそんなもんか、と思ってもらいつつ、以下の動画を見ることをおすすめします。この動画では、非常にわかりやすく、JavaScript の実行モデルの概念を説明してくれています。英語ですが、字幕付きで スロー再生すれば理解には困らないと思います。
What the heck is the event loop anyway? | Philip Roberts | JSConf EU
またagent
の複数のまとまりとして agent cluster
と呼ばれるものがあり、これは agent
の集合体です。
agent
が一つの実行モデルだとしたら agent cluster
は複数の実行モデルの集合であり、これは互いに SharedArrayBuffer
というメモリを共有しながら、agent
ごとに別スレッドとして実行が可能です。これはマルチスレッドを可能とするための仕組みとして導入されたものであり、 web worker
などで利用されています。
今回は話を複雑にしないため agent
1 つでのシングルスレッドでの実行を考えます。ブラウザ上での JavaScript 非同期関数を理解する上では、agent
1 つでのシングルスレッドでの実行を考えれば十分です。
次回
この記事では JavaScript の歴史や特徴、実行環境について概要を整理しました。
次回は、実行モデルについてより詳しく見ていきたいと思います。
- 動画でなんとなく概要はわかったけど、よくわからない単語がたくさん出てきて結局よくわからない
そんな疑問に答える第 2 章は JavaScript 実行モデル (ECMAScript が定める実行モデル) です。
参考資料
HTML Living Standard
ECMAScript® 262 Language Specification
What the heck is the event loop anyway? | Philip Roberts | JSConf EU
Further Adventures of the Event Loop - Erin Zimmer - JSConf EU 2018
JavaScript execution model