【JavaScript入門】varの使い方とlet,constとの違いについて解説 | プログラミング入門ならWEBCAMP NAVI
【12月枠も残りわずか】転職保証コース

【JavaScript入門】varの使い方とlet,constとの違いについて解説

JavaScript

varは、JavaScriptの参考サイトや書籍のサンプルプログラムで必ず目にすると言っても良い単語でしょう。

このvarを、変数を定義するための「おまじない」のように思っていないでしょうか?varはただのおまじないではありません。
変数を宣言して使えるようにする重要な役割があるのです。

また、変数を宣言するものはvarだけではなく、letやconstなどもあります。

実は、これらを適切に使うことでプログラム内の見やすさ(可読性)を上げ、不具合を未然に防ぐことができるのです。つまりvarは、JavaScriptを扱うに当たってとても重要なポイントと言えるものなのです。

今回は、そんなvarletconstについて、詳しく解説していきます。変数変数宣言について、改めて理解していきましょう。

varで変数を宣言する

数多くの参考サイトや書籍で使われているvarですが、具体的にどういった構文何ができるのか、ちゃんと理解しているでしょうか?

ここでは、そんな基本的な部分を詳しく解説していきます。派手な処理や動きはありませんが、重要な部分なのでしっかりと押さえておきましょう。

変数は値が入る箱

変数というのは、各種の文字文字列配列などのオブジェクトを格納するものです。

数値やデータに名前を付けて処理を記載することで、汎用的な条件(色々な数値やデータ)でプログラムが動くようにするわけです。

つまり、プログラムを使って何らかのデータを扱う上で、必ず必要なものと言えるでしょう。

値やデータに名前を付けたものですので、もちろん変数にはプログラム内での決まった用途意味があります。それに沿ってきちんと扱わなければ、不具合を生んでしまいます。

そのため、変数を正しく扱うには制限を設けた方が安全なのです。その観点から、変数宣言を行うvarやlet、constについて学んでいきましょう。

varで変数を宣言しよう

では、varの使い方を説明していきます。

すでに使ったことがある人も多いと思いますが、簡単だからこそ、実は奥の深いものです。「分かっているつもり」は不具合の元ですので、必ず目を通しておくようにしましょう。

基本構文は簡単

varの構文は、次のようになっています。

  var 変数名[ = 値][,変数名2[ = 値2]] [,変数名3[ = 値3]]... [,変数名n[ = 値n]];

構文の形で見ると、少しややこしく感じるかもしれません。[]の部分は省略可能で、同じ内容が繰り返されていますので、単純に書くと、以下のどちらかになります。

  var 変数名;
  var 変数名 = 値;

あとは、「,」で区切って「変数名」や「変数名 = 値」をいくつでも繰り返して、まとめて宣言できるわけです。

値を代入する場合は、変数はその値で初期化され、代入されない場合は、「undefined」という無効なことを表す値が格納されます。

なお、varによる変数宣言は、どこでも行うことができますが、同じ変数名で何度も宣言することはできません。(スコープが違えば可能ですが、詳しくは後述します)

また、変数宣言をプログラムの先頭で行う必要はなく、むしろその変数を使用するプログラムコードのあとに宣言してもエラーにはならないのです。(いくつかのプログラム言語では、関数の先頭などで変数宣言しなければいけません)

varによる変数宣言は、必ず最初に行われる(varの巻き上げ)
変数宣言が、使用するコードのあとでもかまわない理由は、varの巻き上げによるものです。ほぼすべてのプログラムは、原則としてプログラムコードを上から下へ実行します。しかし、JavaScriptは、処理を開始する前に「varを探し出して、変数宣言を先に実行する」のです。そのため、以下のプログラムコードはエラーになりません。

document.write(value);
var value =10;

ただし、エラーになりませんが、実行結果は「undefined」が表示されます。

つまり、宣言は先に行うが、初期化(値の代入)は通常通りの順番で行うということです。気を付けましょう。

変数名の付け方

JavaScriptの変数名は、次の条件を満たしておかなければいけません。

・先頭文字は、以下のいずれかであること
アルファベット(”A” から “Z”(大文字)と “a” から “z”(小文字))
アンダースコア (_)
ドル記号 ($)

・以下の文字種で構成されていること
アルファベット(”A” から “Z”(大文字)と “a” から “z”(小文字))
アンダースコア (_)
ドル記号 ($)
数字 (0-9)

数字で始まる変数名は認められていないので、注意しましょう。

また、「var」や「break」などの予約後も変数名として使えませんので、気を付けなければいけません。

varの使い方

では、具体的にいくつかのパターンで、変数宣言をしてみましょう。

まずは基本的な変数宣言です。

  var name1;             // undefined
  var name2 = 10;        // 10
  var name3 = "value";   // 文字列"value"

上記は、以下のよう書くことも可能です。

  var name1, name2 = 10, name3 = "value";

改行や余計なスペースがあってもかまいません。

  var name1, 
        name2 = 10,
        name3 = "value";

型はいらない

変数の型というのは、その変数に格納できるデータの種類(整数、浮動小数、文字、オブジェクトなど)を指定するものです。

実は、多くのプログラミング言語で、変数宣言時に「変数の型」の指定が求められています。これは、変数の用途を制限し、勘違いによる不具合の混入を防ぐ効果があります。

しかし、最初に指定するが故に、仕様変更などによるプログラムの修正箇所をいたずらに増やし、影響範囲と修正工数が増える原因にもなっています。

そのため、JavaScriptでは変数の型を宣言時に指定するのを止め、代入時に自動で設定するようになっているのです。

JavaScriptでは、varなどで変数宣言するときに型を意識する必要がありません。

varと良く似たletとconst

ES2015から変数宣言をする方法に、letconstという、2種類の方法が加わりました。

使い方(基本構文)がまったく同じで、動作も「変数宣言」であるこの2種類について、varとの違いを主に紹介します。

実は、今後はこの2つを使った方か良いのです。

使い方は同じ

念のため、letとconstの基本構文を紹介します。

  let 変数名[ = 値][,変数名2[ = 値2]] [,変数名3[ = 値3]]... [,変数名n[ = 値n]];
  const 変数名 = 値[,変数名2 = 値2][,変数名3 = 値3]... [,変数名n = 値n];

letは、varとまったく同じになっていますが、const必ず初期化しなければいけない形になっています。

varとletの違い

まず、varとletの違いを説明していきます。

この2つのもっとも大きな違いは、「変数をどこで使えるか」という点です。これは「変数のスコープ」と呼ばれるもので、多くのプログラムでとても重要な概念なのです。

varとletのスコープについて、それぞれ具体的に説明しましょう。

varのスコープ(関数スコープ)

varで宣言した変数は関数スコープを持っています。

関数スコープというのは、関数内で宣言した場合は関数内でのみアクセスできるというものです。ローカルスコープとも呼ばれています。

つまり、関数内で宣言した変数には関数外からアクセスできません。そのかわりに、関数内と関数外で同じ名前の変数があっても問題なく、それぞれ別物として処理されます。

これは、大規模な開発ではとても重要な機能です。例えば、AさんとBさんが別の関数を作っているとして、偶然同じ変数目になる可能性はあるでしょう。このとき、変数が関数スコープを持っていなければ、どちらの変数を使われているのか分からず、思わぬ不具合が発生することでしょう。

具体的には、以下のプログラムを動かしてみてください。

html
  body
    script type=text/javascript

var msg = "Top!";
function localFunc(){
  var msg = "localFunc!";
  document.write("local=" + msg + "");
}
localFunc();
document.write("top=" + msg + "");

    /script
  /body
/html


関数内からの表示は関数内の変数msgの内容、関数外の表示は関数外の変数msgの内容を表示しています。

なお、関数スコープの変数は、関数の処理が完了すると使えなくなります。(格納された値が保持されていることが、保証されなくなります)

letのスコープ(ブロックスコープ)

letで宣言された変数はブロックスコープを持つため、varで宣言された変数よりもアクセスできる場所が制限されています。

ブロックというのは、forやifなどの{}で囲まれている部分のことを指します。つまり、letを使って宣言された変数は、if文の外からはアクセスできないのです。

こちらも、具体的なプログラムコードで確認しておきましょう。

html
  body
    script type=text/javascript

let msg = "Top!";
function localFunc(){
  let msg = "localFunc!";
  if(msg != "") {
    let msg = "Block!"
    document.write(" if in local=" + msg + "");
  }
  document.write("local=" + msg + "");
}
localFunc();
document.write("top=" + msg + "");

    /script
  /body
/html

同じ名前の変数が定義されているというエラーが出ることなく、またそれぞれのスコープの変数の内容を表示していることが確認できます。

関数スコープと同様に、ブロックスコープの変数はブロックの処理から抜けると使えなくなります。(格納された値が保持されていることが、保証されなくなります)

letは巻き上げられない

varとletのもう1つの違いは、varの特徴の1つでもある「巻き上げ」の動作が違うということです。

varと違って、letで宣言した変数を宣言の前に使用しようとすると、エラーが発生します。

html
  body
    script type=text/javascript&

document.write("var=" + vmsg + "");
document.write("let=" + lmsg + "");
var vmsg = "test";
let lmsg = "test";

    /script
  /body
/html


エラーが発生しているため、変数lmsgの表示処理が行われていません。consoleを確認すれば、「Uncaught ReferenceError: lmsg is not defined」というエラーが発生していることを確認できるでしょう。
※GoogleChromeでconsoleを表示するには、Shift+Ctrl+iを押してください

なお、letで巻き上げが行われていないわけではなく、巻き上げを行った上でエラーを発生させているのですが、現段階ではそこまで気にすることはあまりないでしょう。

constとは?

次にconstについて説明しましょう。

constで宣言した変数の動作は、基本的にletと同じでブロックスコープを持っており、宣言前にアクセスするとエラーが発生します。

しかし、さらに違うのが宣言時に必ず初期化(代入)しなければいけないこと再代入ができないことです。

constで宣言した変数は、代入しようとするとエラーが発生します。

実際のプログラムコードで試してみましょう。

html
  body
    script type=text/javascript

const msg = "Top!";
function localFunc(){
  const msg = "localFunc!";
  if(msg != "") {
    const msg = "Block!"
    document.write(" if in local=" + msg + "");
  }
  document.write("local=" + msg + "");
}
localFunc();
document.write("top=" + msg + "");
msg = "Error!";
document.write("error?=" + msg + "");

    /script
  /body
/html

実行結果はletの場合と同じですが、consoleを確認してみると「Uncaught TypeError: Assignment to constant variable.」というエラーが発生しています。

これは、「const宣言された変数に新たに代入しようとしているので、宣言方法がおかしい」といった意味のエラーです。

top=Top!という文字列まで表示されていますので、その直後の変数msgへ”Error!”という文字列を代入しようとして部分で、エラーが発生していることが分かります。

なお、「再代入ができない」というのが大前提ですが、それはconst宣言した変数そのものだけです。constで宣言した変数に配列を代入した場合、その変数に別の配列を代入することはできませんが、配列に値を代入することはできます。

const arr = [1, 2, 3];

// arr = [4, 5, 6];  // NG!
arr[0] = 4;  // OK!

スコープを改めて整理する

varとlet、constの違いのポイントであるスコープは、プログラムを作る上でとても重要なものです。

最初は窮屈さを感じるかもしれませんが、プログラムを続けていく中で、必ずその恩恵に与ることになることでしょう。

具体例 スコープの広さ
グローバルスコープ varやletなどを使用せずに初期化と同時に宣言された変数 すべてのスコープからアクセス可能
関数スコープ 関数内で宣言された変数 関数内すべてでアクセス可能
ブロックスコープ ブロック内で宣言された変数 ブロック内でのみアクセス可能

無印のスコープ(グローバル)

前述の表で、グローバルスコープというものが初めて現れましたので、少し説明します。
グローバルスコープというのは、varやlet、constを使わずに宣言された変数が持つスコープのことです。

変数宣言の命令を使わないため、初期化と同時に宣言されることになります。

この無印の変数宣言を行った変数は、グローバルスコープというスコープを持ち、どこからでもアクセスすることができるようになります。

つまり、プログラムが実行している間ずっと値を保持して、アクセスできるということです。

具体例を紹介しておきましょう。

html
  body
    script type=text/javascript

msg = "Global!";

function localFunc(){
  if(msg != "") {
    document.write(" if in local=" + msg + "");
  }
  document.write("local=" + msg + "");
}

function localFunc2(){
  document.write("local2=" + msg + "");
  msg = "localChange!";
}

localFunc();
document.write("top=" + msg + "");
localFunc2();
document.write("top=" + msg + "");

    /script
  /body
/html

1つのHTML内で実行される複数のJavaScriptすべてからアクセスできますので、使い方によってはとても便利でしょう。

しかし、変数名が重複する可能性が高いので、変数名には気を遣わなければいけません。

また、いつだれがどんなタイミングで変更するか分かりませんので、管理がとても困難です。安易な使用は控えましょう。

変数宣言の動作確認

変数宣言について一通りの説明が終わりましたので、復習のために練習問題を用意してみました。ぜひ、チャレンジしてください。

練習問題

以下のプログラムで、最後の出力文言が「countの値は[10]?」と表示させる。

var count = 10;

for(var count = 10; 0; count; count--){
  document.write(count + "");
}

document.write("countの値は[" + count + "]");

varではなく、letやconstを使おう

ここまでの説明で、結局、どれを使えば良いのか分からないと思ってしまった人もいるかもしれません。

そこで、ここからは、varとlet、constを使うべきシーンと、その理由について、お伝えします。

結論としては「varではなく、letやconstを使うべき」です。また、原則として、constを使うのがベターでしょう。

詳しく説明します。

varではなくletやconstを使う理由

varではなくletやconstを使う理由は、スコープの違いです。

ここまでに説明してきたように、varは関数スコープ、letやconstはブロックスコープですので、varの方がスコープが広くなっています。

スコープの広い変数の方が「手軽に使える」と考えがちですが、それはあくまでもお試しの簡単なプログラムの場合です。

少し規模の大きなプログラムの場合、最初の意図とは違う用途で変数を使ってしまう(使いまわしてしまう)こともあり、スコープが広いとそれだけそのリスクが上がります。

つまり、関数の中であっても「変数の内容が意図せず変更されてしまう」ことが起きてしまうわけです。

また、スコープが広いと変数名が重複してしまう可能性が上がってしまいます。そのため、1つのプログラムを複数人で対応していると、結合したときに変数の競合が起き、不要な習性が発生してしまうわけです。

特に、繰り返しのカウンターによく使う短い名前の変数にこの傾向が強く、気を付けなければいけません。

そのため、 varではなくletやconstを使うことをおすすめします。

constを使う理由

letとconstのどちらを使っても良いかというと、それはもちろん違います。

最終的には「用途に合わせる」のが正解ですが、何をその基準にすべきかを説明しましょう。

それは、constの性質である「再代入」がポイントです。

再代入しない(計算結果を入れるだけなど)の変数はconst、繰り返し代入する(繰り返し分のカウンターなど)変数はletを使って宣言すれば良いのです。

こうすることで、宣言段階でその変数の大枠の用途が見え、プログラムの可読性も上がります。また、意図せず値が書き換わるリスクも最小限に減らすことができるのです。

可読性を上げて、バグを未然に防ぐため

プログラマーの癖や方針にもよりますが、可読性が高くバグに強いプログラムの多くは、変数を使いまわすことはしません。
つまり、ほとんどの変数が再代入されません

そのため、ほとんどの変数宣言はconstで良いはずです。もちろん、繰り返し分のカウンターなどの明らかに再代入が必要なものはletを使えば良いですが、それ以外はconstで宣言していてまず困ることはないでしょう。

前述の通り、原則constで宣言し、処理上で再代入するしかない場合のみletを使うようにすれば、自然と可読性が高く、バグを埋め込みにくいプログラムになることでしょう。

まとめ

varletconst変数宣言というプログラムの基本的な処理を行う命令です。

そのため、数多くの参考サイトや参考書籍で目にしていることでしょう。しかし、実は中級者でもその意味をきちんと理解できていない人もいます。

しかし、プログラムのコードにはすべて意味があるのです。
意味を理解しなければ正しく扱えず、正しく扱えなければそれが原因で不具合を発生させることもあります。

特に、変数宣言のような基本的な部分が原因の不具合ほど、原因の発見や修正がやっかいなものはありません。

これからステップアップしていく中で、varというありふれた命令の意味も、手を抜くことなくきちんと理解して使っていくようにしましょう。

今回のまとめ
・var、let、constは変数を宣言する命令
・JavaScriptの変数宣言は肩を意識しない
・varは巻き上げられる
・varは関数スコープ
・letはブロックスコープ
・constはブロックスコープで、再代入できない
・const宣言した変数に配列を代入した場合、他の配列を代入できないが、配列に値を代入可能
・var、let、constを使わずに変数宣言(初期化)すると、グローバルスコープになる
・varよりletやconstを使うべき
・再代入しない変数はconst宣言を

練習問題の問題とこたえ

練習問題

以下のプログラムで、最後の出力文言が「countの値は[10]?」と表示して欲しい。修正してください。

var count = 10;

for(var count = 10; 0; count; count--){
  document.write(count + "");
}

document.write("countの値は[" + count + "]");

こたえ

let count = 10;

for(let count = 10; 0; count; count--){
  document.write(count + "");
}

document.write("countの値は[" + count + "]");

12月枠も残りわずか!!

エンジニア転職を目指すなら…

転職保証付きプログラミングスクール

で未経験からエンジニア目指そう

 

✔︎未経験からの転職 ✔︎会社の将来が不安 ✔︎給与や待遇に不満がある

 

転職保証コースは質の高いカリキュラムで転職成功率98%