久しぶりにJavaScriptを使うことになって調べたら、変数宣言のバリエーションが増えていました。let, constという使い方があるらしい。
ES2015で策定されたのでもう2年も前です(執筆時点)。やばい相当遅れています。遅まきながら勉強しました。
ECMAScript(エクマスクリプト)
JavaScriptの仕様のこと。Ecma International(エクマ・インターナショナル)がJavaScriptの書き方を決めている(仕様の策定・勧告)。
実質的な策定作業はTC39が行い、それに基づいてEcma Internationalが勧告する。勧告されると『ES20**(年代)』という名称がつけられる。
Ecma Internationalは、もともとヨーロッパの電子通信に関する標準化団体なので、JavaScriptだけを扱っているわけではない。
ES2015(ES6)
2015年に策定された第6版のこと。JavaScriptの従来の書き方から大幅に改善されたので、インターネット上の情報も多い。
ES2015から1年ごとに仕様を勧告することになったので、公式の名称では版数を使うのをやめた。(ES6は昔の言い方の名残り。正式なドキュメントには書いてある。)
ES6という呼び方は、変化の過渡期なので許されているだけ。
ES2016
2016年に勧告された仕様。ES7という表現が見られるが、ES2016のほうが分かりやすいのでES6ほど一般的じゃない。
ES5
2015年に大幅な変更が行われる前のJavaScriptの仕様。第5版。2009年に勧告。現在、どんなに古いバージョンのブラウザでも動かすことができる基準になっている。
JavaScriptのトランスパイルが簡単にできるようになったので、すべてのブラウザに対応できるJavaScriptの呼び方として使われる。
(トランスパイルは別のバージョンのJavaScriptのプログラムに変換すること。)
ESNext
次世代のJavaScriptの仕様のこと。まだ勧告されていなくてTC39で策定中の仕様のことを指す。
すべてのブラウザが対応していないES2015以降を指して使っていることも多い。
トランスパイルが簡単になったので、Reactなどのフレームワークや、Node.jsのプラグイン開発など、ESNextでプログラミングすることが当たり前になっている。
次世代の仕様なので、短くかんたんに書けることも多く、SPA(Single Page Application)などの大規模・複雑な開発で使われる。
もちろん、Nextの範囲はES20**がリリースされるごとに変わる。その状況は下記リンクにある。
TC39(Technical Committee 39, 専門委員会39)
ECMAScriptの仕様の策定を行う専門委員会。Ecma InternationalはいろいろなTCを持っているので番号が振られている(ECMAScriptの仕様は39)。
作業中の内容や仕様などはGitHubで公開されていて確認できる。
作業は5ステージに分けて行い、すべてのステージが終了するとEcma Internationalが勧告する。
Stage 0 | Strawman たたき台・試案 | どんな仕様を導入するか? 策定作業に 入るか? を決める。 |
Stage 1 | Proposal 提案 | 仕様の策定作業の枠組みを作ったり問 題点の洗い出しを行う。 |
Stage 2 | Draft 下書き・草案 | JavaScriptでじっさいに書く。 プログラミングの書き方を決める。 ドキュメントには『正確に』とあるの で、あいまいなことは残さない。 |
Stage 3 | Candidate 候補 | 一般の開発者にドラフトを公開してフ ィードバックする。 (お試し期間) |
Stage 4 | Finished 完了 | ECMAScriptの標準に追加できる準備 ができている状態。 いつでも勧告できることを表す。 |
各ブラウザは、勧告されるのを待っているわけではなく、独自に先行して導入することもある。その経過は誰でも確認できる。
var いままでの使い方
従来の使い方です。新しい方法が追加されても使うことができます。しかし、let, constがあるので、もう使う場面はありません。
ぼくは使うことをやめました。
let 変数のスコープを限定する
いままで、変数の有効範囲の自由さはJavaScriptの特長でしたが、じっさいはバグの温床になっていました。
これを解決したのが『let』です。
宣言したスコープ内だけ変数が有効になります。スコープとは、変数の見える範囲のことです。
いままでのvarに代わるもので、スコープを限定するので、varではなくletを使うほうがプログラムとして安全です。
if, for内で宣言すると構文内だけ有効な変数です。これまでなかった狭いスコープの変数が使えるようになりました。
var a = true
if(a) {
var b = 'sample';
}
console.log(b); // 'sample'が表示できる。
let a = true
if(a) {
let b = 'sample'; // ifの中でしか見れない。
}
console.log(b); // エラーになる
また、varでは変数の二重宣言ができました。
var a = 'sample';
.
.
.
var a = 'sample2';
console.log(a); // 'sample2'が表示される
letではエラーになります。これはプログラミングでは当たり前のことです。『同じことは書かない』がプログラミングの基本なので。
const 定数。値の変更はできない
定数です。一度値を設定したら変更できません。DOMオブジェクトや関数を変数に格納するときに使います。
constで宣言された変数は値が変更されないことを明示しているので、プログラムソースが読みやすくなります。
var a = 'sample';
a = 'sample2'; // 変更したくない場合でも変更できるのでバグになりやすい
var func = function() {
console.log('sample');
}
var func = function() {
console.log('sample2');
}
func(); // 関数が上書きされる。関数以外でも上書きできるので自由度が高い。
const a = 'sample';
a = 'sample2'; // 変数に値を格納できないのでエラーになる
const func = function() {
console.log('sample');
}
func = function() {
console.log('sample2');
} // エラーになる
まとめ
2018年の現在、varを使うことはないと思っていいです。
いまは、生のJavaScriptを書くことは無くなりつつあります。最新のJavaScriptの仕様で開発して、公開する環境に合わせてトランスパイルするという流れがあるからです。
トランスパイル(transpile)
プログラムを、べつのバージョンや、べつの言語のプログラムに変換すること。
一種のコンパイラ。トランスコンパイラともいう。
JavaScriptは最新の仕様で開発して、任意のバージョンにトランスパイルする手法が一般的になっている。
(新しい仕様のほうがシンプルな記述で読み書きしやすいため。)
@babelが有名。
トランスパイルは文法を変換するが新しいAPI(関数やオブジェクト)までは対応できない。
古いもので確実に動かすためにはポリフィルも必要。
ポリフィル(Polyfill)
プログラムのバージョン違いでAPIが不足するところを補うこと。
プログラム言語はバージョンが上がると新しいAPIを追加する。APIは関数やクラス・オブジェクトのこと。
古いバージョンで動かすときは新しいAPIと同じ機能がないと動かない。それを作るのがポリフィル。
ポリフィルは、新しいAPIを移植するのではなく、古いバージョンのプログラムで実装できるAPIに作り直して提供する。
jQueryのmigrateはjQueryのポリフィル・パッケージ。
トランスパイルで有名な@babelにもポリフィルの拡張機能がある。
どうしても生のJavaScriptを編集しないといけなくても、『昔は、変数宣言にvarを使っていた』程度で大丈夫でしょう。
ただし、varはあまりにも自由度が高いので、バグになりやすいことには注意が必要です。