JavaScriptは一時期は時代遅れな側面がありましたが、時代の変化に合わせてバージョンが変わって新しく機能や構文が追加されてきました。
2015年6月に標準化団体に採択された「ECMAScript 2015(ES2015)」から、通称、ECMAScript 6(ES6)と呼ばれていて、以後、仕様も追加されています。
これまでのavaScriptでももちろん動作しますが、ここからはJavaScriptの新仕様であるECMAScript 6(ES6)について基本的な知識を扱っていきます。。
ここではまず変数宣言のletとconstについて見ていきましょう。
変数宣言のletとconst
JavaScript(ES5)からES6への簡単な変更点(違い)から見ていきましょう。まずは変数宣言について見ていきます。
ES5ではvarと書いた後に変数名を定義していましたが、ES6ではこのvarに変えて、letとconstを書いて変数名を定義します。
ES5の変数宣言var
ES5の変数宣言のvarについてはこちらで扱いました。
復習ついでに、まずはvarを使ったコードをscriptファイルに書いて確認してみましょう。(これまでと同様にHTMLファイルとscriptファイルを関連づけて使います。)
// ES5
var nameEs5 = 'エドワード・エルリック';
var ageEs5 = 16;
nameEs5 = 'ウィンリィ・ロックベル';
console.log(nameEs5);
varで2つの変数、nameEs5、ageを宣言しています。それぞれ値を入れています。
その後、変数nameEs5に新しい値を代入して、console.log()で出力しています。
JavaScriptコンソールに表示してみます。
最初の宣言での値ではなく、書き換えられて値が表示されているのがわかります。
ES6での変数宣言let、const
ES6での変数宣言は、let、constを使います。
上と同じコードをES6で書いてみます。
// ES6
const nameEs6 = 'エドワード・エルリック';
let ageEs6 = 16;
nameEs6 = 'ウィンリィ・ロックベル';
console.log(nameEs6);
letの使い方はvarと同じです。(ただし、あとで説明しますがvarのように重複を許容せず、ブロックスコープで機能します)
constの使い方は、値を変えることができないようにする場合に使います。いわゆる定数として利用します。
先ほどのコードを変数宣言const、letで書き換えています。
実行してJavaScriptコンソールで表示してみましょう。
エラーが表示されています。変数nameEs6をここではconstにしています。ここではこの変数に後から別の値を代入しています。constで宣言された変数は値を変更することができませんから、このようにエラーが出ているわけです。
変数のスコープ
letを使った変数宣言は、先ほども書いたようにこれまでのvarと違いはありません。ただし、スコープの範囲で処理に違いが出てくるのがこの特徴です。
ここではこのスコープの違いを確認していきましょう。
まずES5を使った次のようなコードを用意します。
// ES5
function votingRight5(isJapaneseNationality) {
if (isJapaneseNationality) {
var name = '永野芽郁';
var birthYear = 1999;
console.log('西暦' + birthYear + '年生まれの' + name + 'さんは選挙権があります。');
}
}
votingRight5(true);
votingRight()という関数を定義します。ちょっと面白くないコードですが、選挙権についての関数です。isJapaneseNationalityという引数で日本国籍かどうかを問うています。
関数内の処理として、if文で国籍がどうなのかを判定し、varを使ってnameとbrthYearの変数を保持しています。if文の条件がtrueの時に、console.log()で変数を利用した文章が表示されます。
ここではvotingRight(true)でこの関数を呼び出しています。
実行すると、JavaScriptコンソールには次のように表示されます。
ここまでは問題なく理解できると思います。このコードをES6のconstとletを使って書くと次のようになります。
// ES6
function votingRight6(isJapaneseNationality) {
if (isJapaneseNationality) {
let name = '永野芽郁';
const birthYear = 1990;
console.log('西暦' + birthYear + '年生まれの' + name + 'さんは選挙権があります。');
}
}
votingRight6(true);
nameとbirthYearをそれぞれlet、constで宣言してること以外、全く同じコードです。
これも実行結果は上のコードと同じです。
このES5、ES6の二つのコードを次のように書き換えてみます。(並べて書いてみます)
// ES5
function votingRight5(JapaneseNationality) {
if (JapaneseNationality) {
var name = '永野芽郁';
var birthYear = 1999;
}
console.log('西暦' + birthYear + '年生まれの' + name + 'さんは選挙権があります。');
}
votingRight5(true);
// ES6
function votingRight6(isJapaneseNationality) {
if (isJapaneseNationality) {
let name = '永野芽郁';
const birthYear = 1990;
}
console.log('西暦' + birthYear + '年生まれの' + name + 'さんは選挙権があります。');
}
votingRight6(true);
どちらもconsole.log()をif文のブロックの外に移動させているだけです。
実行すると次のようになります。
ES5のコードは表示されましたが、ES6のコードはエラーになりました。
これは、letとconstで宣言された変数は関数スコープではなくブロックスコープであるからです。if文の中の変数はブロックスコープによってブロックの中でしか参照できないので、このES6のコードでのconsole.log()はif文の外から取り出すことができないというわけです。
逆にES5のvarは関数内での移動でもこちらは関数スコープなので表示されているという違いがあります。
このES6コードで次のように定義すると、ブロック内の変数を利用することができます。
// ES6
function votingRight6(isJapaneseNationality) {
let name;
const birthYear = 1990;
if (isJapaneseNationality) {
name = '永野芽郁';
}
console.log('西暦' + birthYear + '年生まれの' + name + 'さんは選挙権があります。');
}
votingRight6(true);
これはブロックの外側で変数を定義しています。letは変数を宣言しているだけなので、ブロック内で変数の値を入れることでアクセスすることができます。constは定数なので、ブロックの外側で定義します。
こうすることで、エラーなく実行することができます。
この2つのコードで、次の位置にそれぞれconsole.log()でnameを呼び出すコードを入れてみます。
// ES5
function votingRight5(JapaneseNationality) {
if (JapaneseNationality) {
console.log(name); // この位置
var name = '永野芽郁';
var birthYear = 1999;
}
console.log('西暦' + birthYear + '年生まれの' + name + 'さんは選挙権があります。');
}
votingRight5(true);
// ES6
function votingRight6(isJapaneseNationality) {
console.log(name); // この位置
let name;
const birthYear = 1990;
if (isJapaneseNationality) {
name = '永野芽郁';
}
console.log('西暦' + birthYear + '年生まれの' + name + 'さんは選挙権があります。');
}
votingRight6(true);
どちらも変数nameの宣言の前にconsole.log(name)を入れています。
これを実行すると次のようになります。
ES5の方はundefinedと表示されていますが、実行結果が表示されています。ところがES6の方は変数宣言の前に参照しているのでエラーになっています。
変数は定義した後に利用する方が好ましいので、このES6のように宣言前に変数を利用するとエラーになるということは、プログラミングの流れとしては好ましい形になっています。
もう一つ簡単なコードでES6のletとES5のvarの動きを見ておきましょう。
forループ文を使って、次のようなコードを書いてみます。
let i = 30;
for (let i = 0; i < 10; i++) {
console.log(i);
}
console.log(i);
実行すると次のようになります。
for文のブロック中の処理を0から順に行って9まで表示しています。ブロックをここで抜けるので、最初のletで定義したiの30が最後に呼び出されて表示されています。ブロックの中と外とでは同じ変数iでも違うものということです。
このコードをvarで書き換えてみましょう。
var i = 30;
for (var i = 0; i < 10; i++) {
console.log(i);
}
console.log(i);
実行すると次のようになります。上との違いがわかるでしょうか。
こちらはfor文の中の処理が0から9まで行われていますが、カウントが10になった時にブロック内の処理は行われず、iに入れられてたカウントの10で、ブロックの外のiが上書きされ、最終行のconsole.log(i)で表示されているという違いになります。
このようにES5の変数宣言varとES6の変数宣言let、constには動画に違いがあることを理解しておきましょう。
ハガレンのネタもマンネリ化してきたので、変数の値に最近お気に入りの永野芽郁ちゃんをここでは使ってみました(笑)
まとめ
JavaScriptの新仕様であるECMAScript 6(ES6)について、ここでは変数宣言のletとconstについて扱いました。
ES5の変数宣言varとES6の変数宣言let、constとでは動きに違いがあります。
varとletは使い方は同じですが、letは変数の重複を許しません。同じ文字列の変数でも違うものとして扱われます。また、varが関数スコープであるのに対して、letはブロックスコープであることに違いがあります。このために変数を利用する位置に違いが出てきます。
constは定数を定義する宣言となり、途中で値を変更することができません。