前回は、変数の宣言について学びました。それまで、「定義」と言っていたことが、厳密には宣言と代入だったというお話ですね。今回は、その「宣言」についてもう少し詳しく解説したいと思います。
まず、早速ですが、変数の宣言方法は1種類だけではありません。3種類存在します。より厳密にいうと、パート1でJavaScriptのバージョンの話をしましたが、バージョン「ES5」までは1種類しか存在しなかったんですけど、「ES6」になったときに2種類追加して、合計3種類になったんです。
現在のプログラムでは、変数の宣言は下記のように行なっています。
const g = ca.getContext( '2d' ); // 変数gを宣言。代入内容は不明
これで言うと、「const g」の部分が変数の宣言にあたります。「g」は変数ですので、「const」が宣言に該当すると想像できるのではないでしょうか?
そして、「const」以外にも変数の宣言を行なえるキーワードが、実は2種類存在します。「let」と「var」です。試しに、既存プログラムの「const」部分を書き換えてみて下さい。何の問題もなく動作すると思います。
window.onload = function( ev ) // 文ではない何か
{ // 不明な行
var ca = document.getElementById( 'main' ); // 変数caを宣言。代入内容は不明
let g = ca.getContext( '2d' ); // 変数gを宣言。代入内容は不明
g.font = "40px monospace"; // 変数gの書体を40ドットへ
g.fillStyle = "#ff0000"; // 変数gの描画色を赤へ
g.fillText( "こんにちは世界", 40, 80 ); // 変数gへ文字列を描画
} // 不明な行
constをletやvarに置き換えても、何も変わらず動作しました。では何故似たようなものが3種類も存在するのでしょうか? その解説を理解するには、まずは過去の歴史を知っておく必要があります。
最初にお話しした通り、JavaScriptバージョン「ES5」までは1種類しか存在しませんでした。それは「var」です。ES6になって「let」と「const」が追加されました。何故追加されたのかというと、varには色々と問題があったからです。
「問題があった」という言い方は必ずしも正しくはないかもしれません。「varが悪い」と感じるかどうかは、個人の主観によるところも大きいですからね。「varのほうが好きだ!」という方も一定数居るかもしれません。「letやconstなど必要ない! オレはvar一筋だぜ!!」という一途な想いを否定するつもりはありませんので念のため。
けれども、varだけでは満足できない声が多かったから、letやconstが追加されたのも事実です。その割合がどれくらいなのか、具体的な比率は分かりませんが、私は「let/const」派です。なので、この講座では「let/const」を使用していきたいと思います。ちなみに、「var一筋」派と「let/const」派が大部分で、「3つとも使用する」という派閥は基本的には無いと思われます多分……。
今まで何度も出てきた話ですが、
let g = ca.getContext( '2d' ); // 変数gを宣言。代入内容は不明
は、「宣言」と「代入」2つの処理を1文で行なっています。では、この2つの処理を1つずつに分割は出来ないのでしょうか? もちろん出来ます。分割した場合は、下記のようなプログラムになります。
window.onload = function( ev ) // 文ではない何か
{ // 不明な行
var ca = document.getElementById( 'main' ); // 変数caを宣言。代入内容は不明
let g; // 変数gを宣言
g = ca.getContext( '2d' ); // 変数gへ不明な何かを代入
g.font = "40px monospace"; // 変数gの書体を40ドットへ
g.fillStyle = "#ff0000"; // 変数gの描画色を赤へ
g.fillText( "こんにちは世界", 40, 80 ); // 変数gへ文字列を描画
} // 不明な行
こんな感じで記述できます。問題なく動くことを確認したら、試しに「let」を「const」へ戻してみましょう!
const g; // 変数gを宣言
g = ca.getContext( '2d' ); // 変数gへ不明な何かを代入
問題なく動くと思いきや、今度はエラーが出てしまいます。
エラー内容の解析は、Google翻訳先生の出番ですね! 早速翻訳してみます。
英語が超絶苦手な私ですが頑張りますw
「定数は初期化する必要があります」
という訳文のうち、「Const」が「定数」、「initialized」が「初期化」に該当するのでしょう。
以前のパートでは「define」をGoogle翻訳先生に頼んで「定義」と訳してもらい、「定義」について色々検討しました。今回も、「初期化」について以前のように考えてみるのも良いんですが、まあここは直ぐに回答してしまいましょう! 「変数を宣言して、何かを代入」することを「初期化する」といいます。
Google翻訳先生は、「Const」を「定数」と訳してくれましたが、そのまま「Const」にしておくと、訳文は、
「Constは初期化する必要があります」
となります。これに私の意訳を少し加えて、
「『const』を使用するには、初期化する必要があります」
と訳したいと思います。これがconstとletの違いです。
変数宣言時、その場で初期化する必要が、
ない:let
ある:const
letとconstの違いは、初期化が必要かどうか以外には、「再代入が可能かどうか」というものもあります。「再代入」が何なのか、まだ学習していませんが、letが可能で、constは不可能です。まとめると、constはletと違い、
「宣言と同時に代入が必要であり、再代入も出来ない」
となります。letに比べて制約が多いだけの存在がconstになります。では逆にconstの利点は何なのかというと……実は機能的な利点は何も無いんです。例えば、既存プログラム上のconstを全てletに置き換えても、ちゃんと動作します。
機能的な利点が無い物の存在意義。これをプログラミング入門者の方に理解していただくのは非常に難しいです。なのでここではこれ以上解説しません。ただ、constを適切に使用することによって、バグの発生を抑えることが出来る、ということだけは頭に入れておいて下さい。それを実感できるようになるのは、残念ながら当分先です。
ちなみに、let/constとvarの主な違いは、「スコープ」というものなんですが、「スコープ」についての解説についても、かなり先の話になります。ただ、これも基本的には、バグ発生の抑制に関する話だと思っていて下さい。「スコープ」に関して、let/constのほうが、varに比べてバグが発生しにくい仕様になっています。が、これに関しては個人の主観によるところもあるので、私がそう思っているだけだという言い方も出来ます。まあ、この手のキーワードでググっていただければ、そう考える人の割合のほうが圧倒的に多いと実感してもらえると思いますけどね。
最後に、用語の話ですが、変数に関して、
「宣言と同時に代入を行ない、その後再代入しない」
変数のことを「定数」と呼びます。constの制約そのままですね。つまり、constで宣言した変数は、「定数」となります。Google翻訳先生が「Const」を「定数」と訳してくれましたが、これはプログラミング用語的にも正しい翻訳です。