JavaScriptには変数の巻き上げという現象があります。「巻き上げ」とは,下の例の場合,yobidasi関数を呼び出すと,右のコメントアウトのとおり出力されることをいいます。
var namae = "YUMI"; function yobidasi() { console.log(namae); //undifined var namae = "KAYO"; console.log(namae); //KAYO } yobidasi();
var namae = "YUMI"; function yobidasi() { var namae;//ローカル変数は,関数内のどこに書かれていても,1行目で何はともあれ宣言された形になります。 console.log(namae); namae = "KAYO";//ここで値が代入されたとみなされます。 console.log(namae); } yobidasi();
このような予測しにくい変数の振る舞いを避けるため,新しく「const」と「let」という変数の宣言方法ができました。
letと同じくブロックスコープで、巻き上げは行われるが宣言前の参照がエラーになる点も同じです。ただし、constで宣言された変数は、再代入が不可能になります。
const x = 10; x = 20; // 再代入はerror
注意したい点としては、他のプログラミング言語ではconstというキーワードはコンパイル時定数になることがほとんどですが、JavaScriptでは単に再代入不可になるだけということです。つまり、JavaScriptにおけるconstは、他のプログラミング言語におけるfinalと同じ動きをします。 constは、ほぼletと同じです。letとの違いは再代入が可能か否かだけです。constを使うのは変数への再代入が不要な場合、あるいは再代入されたくない場合になります。
const pi = 3.14;
また。消費税を計算する場合も消費税は一定で再代入不要なのでconstを使う。 消費税の場合は、税率が変わった際に変数を1箇所だけの修正で済むので、不具合が起こりにくくなる。
const tax = 0.08;
一見、変数というと、”変数”という名前の通り、代入できた方が便利そうですが、プログラムを組む上で、1箇所を修正すれば、全体に反映される方が、前述の消費税のようにときどき変わる値を修正にするには有効です。また、不必要に”変数”にしてしまうと、バグの発生の可能性が高まります。
そのため、基本的には、このconstを使うのが良いとされます。
逆に再代入が必要な変数についてですが、主に使わるのは、繰り返し処理です。
for(let i = 0; i < 100; i++) { console.log(i); }
といった変数の使い方をするとき、変数iは増減しないと困りますね。そこで、再代入が可能なletを使います。ただし、繰り返しの中で使う変数は、基本通り、constを使うべきです。
for(let i = 0; i < 100; i++) { const value = i * 2; console.log(value); }
この場合、一見、valueに再代入しているように見えるが、再代入ではなく、再定義(初期化)しているので、再代入にはならない。
ただし、繰り返し回数が極端に多くなる場合、都度初期化しているので、若干、スクリプトの実行速度が遅くなるという弊害が起こる可能性がある。
varは、JavaScriptにおいて変数を宣言する上で、最も基本的な方法です。varで宣言された変数は関数スコープとなり、宣言のスコープ先頭への巻き上げ(Hoisting)が行われます。 ※変数のスコープについてはここでは解説しません。
var x = 10; x = 20;
JavaScriptの変数宣言にはvarしかありませんでした。変数を宣言する唯一の方法だったのです。letとconstは新たに追加された宣言方法です。そのため、古いブラウザでも何の問題なく動くのが”var”になります。
しかし、現在ではvarを使う理由はありません。関数スコープおよび巻き上げのせいで、挙動の予測が困難になるからです。varを使うのは、古いブラウザを対象にした場合のみになります。モダンブラウザを対象にする場合は、varの代わりにletを使用していく方が良いでしょう。
一言で言うと、変数のスコープがブロックスコープか関数スコープかの違いです。 letを使った場合、ブロックレベルで変数のスコープが定義されるため、以下の例のように1,2,1と表示されます。
function f() { let x = 1; console.log(x); { let x = 2; console.log(x); } console.log(x); } f() // 1 // 2 // 1 varは関数でのスコープのため、以下のように1,2,2と表示されます。 function f() { var x = 1; console.log(x); { var x = 2; console.log(x); } console.log(x); } f() // 1 // 2 // 2
ES6からはletが使えるため、今後はvarではなく好んでletが使われるようになるかと思います。