JavaScript

JavaScriptは、プログラミング言語であり、HyperText Markup LanguageやCascading Style Sheetsと並ぶ　 World Wide Webの中核技術の一つである。

プロトタイプベースのオブジェクト指向スクリプト言語であるが、クラスなどのクラスベースに見られる機能も取り込んでいる。

利用される場面はウェブサイト、ウェブアプリケーション、バックエンド、デスクトップアプリケーション、モバイルアプリケーションなど、ウェブブラウザからサーバ、デスクトップからスマートフォンまで多岐にわたっている。

Javaと似た名称を持つが、異なるプログラミング言語である。

1. 概要
-----

JavaScriptはWebブラウザNetscape Navigatorに起源を持ち、現在では様々な用途に利用されるプログラミング言語である。

JavaScriptの言語仕様はECMAScriptとして標準化され、実装は各種のJavaScriptエンジンによって提供されている。JavaScriptエンジンの例としてChromium系ブラウザのV8、Mozilla FirefoxのSpiderMonkey、SafariのJavaScriptCoreが挙げられる。

言語仕様を定義するECMAScriptのほかに、WebブラウザへアクセスするためのAPI仕様にDOMなどがある。これらはECMAScriptから独立しており、JavaScriptからも独立した概念である。

2. プログラミング言語としての特徴
------------------

JavaScriptは以下のような様々なスタイルのプログラミングが可能である。

if・forなどの制御構造による手続き型プログラミングスタイル
.prototype・classなどのオブジェクトによるオブジェクト指向プログラミングスタイル
map・高階関数などの関数操作による関数型プログラミングスタイルこれらを可能にしているプログラミング言語としての特徴に、以下のことが挙げられる。オブジェクト指向の面では、JavaScriptのオブジェクトはクラスベースではなくプロトタイプベースである。関数型の面では、第一級関数をサポートし関数を第一級オブジェクトとして扱える。

AptanaやEclipse, NetBeans, IntelliJ IDEAなどの統合開発環境はJavaScriptをサポートしており、大規模開発が可能になっている。さらにExt JSなどの本格的なGUIライブラリの登場により、デスクトップアプリケーションと遜色ないユーザインタフェースの構築が可能になった。

2.1. 並行処理
---------

JavaScriptではしばしば、ネットワークを介したリクエストのような "待ち" がある処理を行う。これに対処するために非同期処理をサポートし並行処理が可能となる。

もしも待ちの間にプログラムを停止/sleep させると、その間に他の処理をそのスレッドで行うことが出来ない。もしネットワークリクエストが返ってくるまでブロッキングしたとすると、その間ブラウザのレンダリングも停止してしまう。

非同期処理を記述する方法としてコールバック関数がある。JavaScriptはコールバック関数記法をラップするPromise、Promiseを同期的なコードのように記述できるAsync/await構文をもつ。

またJavaScriptは並列処理による並行処理もサポートしている。

2.2. 並列処理
---------

JavaScriptでは複数スレッドを用いた並列処理が可能である。共有メモリ上のバッファを表現するSharedArrayBuffer、バッファ操作オブジェクトAtomicsが定義されている。スレッドそのものの仕様は環境ごとに異なる。ブラウザの場合はWorker、Node.jsの場合はworker_threadsで定義されている。ただこの2環境ではほぼ共通の仕組みとなっており、例えばpostMessageによるメッセージングが両者でサポートされている。

3. 歴史
-----

3.1. 誕生
-------

JavaScriptはネットスケープコミュニケーションズのブレンダン・アイクによって、1995年5月に10日間で開発された。上司からの指示に「Javaのような外観にしてくれ」「初心者に優しく」「Netscapeブラウザのほとんどなんでも制御できるように」との注文があった。Netscape Navigator 2.0で実装された。

開発当初は//LiveScript//と呼ばれていたが、1995年にサン・マイクロシステムズが開発したプログラミング言語Javaが当時大きな注目を浴びており、ネットスケープとサン・マイクロシステムズが業務提携していた事もあったため、JavaScriptという名前に変更された。最初のJavaScriptエンジンはブレンダン・アイクによりNetscape Navigatorのために作成されたものであった。このエンジンはSpiderMonkeyと呼ばれており、C言語で実装されていた。また、全てJavaで記述されたJavaScriptエンジンであるRhinoも同じくNetscapeのNorris Boydらにより作成された。

1996年にマイクロソフトのInternet Explorer 3.0に搭載されるようになると、その手軽さからJavaScriptは急速に普及していく。1997年、通信に関する標準を策定する国際団体EcmaインターナショナルによってJavaScriptの中核的な仕様がECMAScriptとして標準化され、多くのウェブブラウザで利用できるようになった。

ネットスケープは、ウェブアプリケーション開発言語として自社のサーバ製品に実装したLiveWire JavaScriptも発表したが、こちらはあまり普及しなかった。

JavaScriptの登場初期は、ブラウザベンダー間で言語仕様の独自拡張が行われていたため、ブラウザ間の互換性が極めて低かった。ECMAScriptの策定以降は実装間の互換性は向上し、DOMなど関連仕様の実装に関する互換性も高くなっていった。

かつてはJavaScriptという言葉が「ECMAScript標準」を指す、あるいは「独自実装を含んだ広義のJavaScript」を指し幅広い意味で使われていた。ゆえにどちらの意味でJavaScriptという言葉が使われているかは文脈で判断する必要があった。たとえばかつてマイクロソフトによる実装はJScriptと呼ばれたが、JScriptをJavaScriptと呼ぶような場面があった。

ECMAScriptは仕様自体に独自の拡張を条件付きで認める記述があり、ブラウザが実装しているスクリプト言語はすべてECMAScriptに準拠していることになる。広義の意味でこれをJavaScriptと呼ぶ場合、主要なブラウザが実装しているスクリプト言語はマイクロソフトやGoogle、Appleの実装も含めてJavaScriptである。

実装間での差異を吸収するためにPrototype JavaScript Frameworkなどのライブラリが用いられた。

3.2. 発展
-------

市場のブラウザ間互換性がある程度確立された2000年ごろには、GoogleやAmazonなどのGAFAMもJavaScriptを積極的に利用し始めた。

また、JavaScriptはウェブブラウザの拡張機能を開発するための言語としても使われるようになった。当初は拡張機能用のAPIが統一されていなかったが、互換性を高めようとする動きがある。

当初はインタプリタ方式で実行されることが一般的であったためJavaScriptの実行速度はさほど速くなかったが、現在ではJITコンパイルなどを利用した各種の最適化がなされており、各ウェブブラウザのベンダーともに高速化を図ってしのぎを削っている。さらには、この高速化を受ける形で、Node.jsのようにサーバサイドでもJavaScriptを使う動きが見られるようになった。

3.3. JavaScript 2.0
-------------------

次世代のJavaScriptとして、"JavaScript 2.0" を作ろうとした動きは2度あったが、いずれもまとまらなかった。

1度目はECMAScript 3が完成したのち2000年から2003年にかけて発生したが、ネットスケープとマイクロソフトの対立でまとまらなかった。当時ネットスケープが提案していた案はアドビのActionScript 2.0に引き継がれ、マイクロソフトの案はJScript .NETへと引き継がれた。

その後もネットスケープ及びMozilla FoundationはECMAScriptの策定に並行してJavaScriptを拡張し、JavaScript 1.x系列としてバージョンアップを繰り返していた。ECMAScript側ではECMAScript 4の策定が1999年以降進められており、2006年の時点でMozilla Foundationはこれに基づいてJavaScript 2.0を作成することを表明していた。MozillaはECMAScript 4の策定にあたって、Pythonの文法を一部取り込んだ案を提案しており、自身でもこれを実装していた。

しかしその後、ECMAScriptの標準化作業がMozilla, Adobe, Opera, Googleらが推す ECMAScript 4 と、Microsoft, Yahoo! らが推す ECMAScript 3.1 に事実上分裂してしまった影響から、2008年8月に大きな方針転換があり、ECMAScript 4は破棄され後者がECMAScript 5として2009年に標準化された。ECMAScript 4に入る予定だった機能は新たに発足した「ECMAScript Harmony」に先送りとなった。これは後にECMAScript 2015として標準化が完了した。

なお、ECMAScript 5が標準化されて以降、MozillaのJavaScript実装はECMAScriptへの準拠を謳うようになった。そしてバージョン番号での呼称は行われなくなり、JavaScript 2.0は事実上死語となった。

4. 文法
-----

4.1. 基本的な文法
-----------

JavaScriptの変数は var, letおよびconst キーワードを使用して宣言できる。

let x; // 変数xの宣言。値が未指定のため、特殊な値である undefined が入った状態となる。 let y = 2; // 変数yの宣言。同時に 2 が代入される。 const z = 5; // 定数zの宣言。同時に 5 が代入される。定数であるため、書き換えることはできない。

上記例のスラッシュ2文字以降はコメントである。

JavaScriptは言語仕様にI/Oが組み込まれておらず、それらは実行環境により提供される。ECMAScript 5.1の仕様では以下のように言及されている。

この仕様の中では外部データの入力または計算結果の出力は供給しない。
 しかし、ほとんどの実行環境はConsole Standardで規定されている console オブジェクトを持っており、そこにコンソール出力を行える。以下に最小のHello worldプログラムを示す。 console.log;

再帰関数は以下のように書ける。 function factorial { if  { return 1; } return n * factorial; }

無名関数の構文とクロージャの例は以下である。 // ECMAScript 5以前の記法 var displayClosure = function { let count = 0; // ECMAScript 2015以降で可能な記法 return => { return ++count; }; } var inc = displayClosure; inc; // 1 が返る inc; // 2 が返る inc; // 3 が返る

可変長引数は以下のように記述する。 var sum = function { let x = 0; for  { x += v; } return x; } sum; // 6 が返る

即時実行関数式  の例。関数を用いることで変数をクロージャに閉じ込めることができる。

var v; v = 1; var getValue =  { return function {return v;}; });

v = 2;

getValue; // 1 が返る<WtXmlEndTag />

4.2. 複雑な例
---------

以下のサンプルコードは、様々なJavaScriptの機能を示したものである。

"use strict"; // strictモードの宣言 /* 2つの数値の最小公倍数を求める */ function LCMCalculator { // コンストラクタ関数 const checkInt = => { // 入れ子の関数 if  { throw new TypeError; // 例外のスロー } return x; }; // 行末のセミコロンは省略可能な場合があるが、省略は推奨されない。 this.a = checkInt this.b = checkInt; } // オブジェクトのプロトタイプはコンストラクタ関数の prototype プロパティに格納する LCMCalculator.prototype = { // オブジェクトリテラル constructor: LCMCalculator, // このようにプロトタイプを上書きする場合は、 // constructorプロパティにコンストラクタ関数名を再指定する gcd: function  { // 最大公約数を計算するメソッド // 「ユークリッドの互除法」アルゴリズムで計算 let a = Math.abs, b = Math.abs; if  { // 変数の入れ替え const t = b; b = a; a = t; } while  { const t = b; b = a % b; a = t; } // 最大公約数の計算は一度でよいため、自分自身を計算済みの結果を返すメソッドで再定義する。 // // なお 'gcd' === "gcd", this['gcd'] === this.gcd である。 this['gcd'] = function  { return a; }; return a; }, lcm : function  { // 最小公倍数を計算するメソッド // 変数名は、オブジェクトのプロパティと衝突しない。例）（例: Electron
）