変数と宣言

プログラミング言語には、数値などのデータに名前を付けることで、繰り返し利用できるようにする変数という機能があります。

JavaScriptでは、「これは変数です」という宣言をするキーワードとして、 varletconstの3つがあります。

この章では、変数の宣言方法を見ていきます。

var

varキーワードを使い変数宣言ができます。

たとえば、次のコードでは、bookTitleという変数を宣言しています。 この場合、bookTitleは値が代入されていないため、デフォルト値としてundefinedで初期化されます。 (undefinedは値が未定義ということを表す値です)

var bookTitle;

このbookTitleという変数には、=演算子を使うことで値を代入できます。 =演算子の右側には変数へ代入する値を書きますが、ここでは"JavaScriptの本"という文字列を代入しています。

var bookTitle;
bookTitle = "JavaScriptの本";

変数宣言と同時に初期値の代入もできます。 次のコードでは、bookTitleという変数を宣言し、同時に"JavaScriptの本"という文字列で初期化しています。

var bookTitle = "JavaScriptの本";

また、変数宣言は ,(カンマ)で区切ることにより、同時に複数の変数を定義できます。 次のコードでは、bookTitlebookCategoryの変数を順番に定義しています。

var bookTitle = "JavaScriptの本",
    bookCategory = "プログラミング";

これは次のように書いた場合と同じ意味になります。

var bookTitle = "JavaScriptの本";
var bookCategory = "プログラミング";

変数名に使える名前のルール

変数名の名前(識別子)には、次のルールがあります。 このルールは関数の名前も同じです。

  1. 半角のアルファベット、_(アンダースコア)、$(ダラー)、数字を組み合わせた名前にする
  2. 変数名は数字から開始できない
  3. 予約語と被る名前は利用できない

変数の名前は、半角のアルファベットであるAからZ(大文字)とaからz(小文字)、_(アンダースコア)、$(ダラー)、数字の0から9を組み合わせた名前にします。JavaScriptでは、アルファベットの大文字と小文字は区別します。

これらに加えて、ひらがなや一部の漢字なども変数名に利用できますが、全角の文字列が混在すると手間がかかるためお勧めしません。

var $; // OK: $が利用できる
var _title; // OK: _が利用できる
var jquery; // OK: 小文字のアルファベットが利用できる
var TITLE; // OK: 大文字のアルファベットが利用できる
var es2015; // OK: 数字は先頭以外なら利用できる
var 日本語の変数名; // OK: 一部の漢字や日本語も利用できる

変数名に数字を含めることはできますが、変数名を数字から開始はできません。 これは変数名と値としての数値が区別できなくなってしまうためです。

var 1st; // NG: 数字から始まっている
var 123; // NG: 数字のみで構成されている

また、予約語として定義されているキーワードは変数名には利用できません。 予約語とは、varのように構文として意味をもつキーワードのことです。 予約語の一覧は予約語 - JavaScript | MDNで確認できますが、基本的には構文として利用される名前が予約されています。

var var; // NG: `var`は変数宣言のために予約されているので利用できない
var if; // NG: `if`はif文のために予約されているので利用できない

先ほど紹介したように、変数の宣言に利用できるキーワードとして、var以外にもletconstがあります。 どちらも変数宣言の一種で、利用できる変数名のルールは同じとなります。

それでは、次はletconstについて見ていきます。

[ES2015] let

letキーワードを使い、現在のスコープに対して変数宣言できます。

letの使い方はvarとほとんど同じです。 次のコードでは、bookTitleという変数を宣言し、同時に"JavaScriptの本" で初期化しています。

let bookTitle = "JavaScriptの本";

letvarは、スコープの扱いと同じ変数名の再定義の扱いが異なります。 スコープについては「関数とスコープ」の章で扱うため、現時点では「よりよいvar」ということだけ覚えておくとよいです。

letconstは、同一スコープ内で同じ変数名を再定義できません。 次のように同じ変数名で再定義しようとする構文エラー(SyntaxError)になります。 これにより、間違えて変数を二重に定義してしまうというミスを防ぐことができます。

let x; // "x"を定義する
let x; // 同じ"x"を定義するとSyntaxErrorとなる

一方、varは同一スコープ内で同じ変数名を再定義できます。 これは意図せずに同じ変数名を定義し、値を上書きしてしまう問題があるため、varを避ける理由の1つとなります。

var x = 1; // "x"を定義する
var x = 2; // 同じ変数名"x"を定義できる
// 変数xは2となる

[ES2015] const

最後にconstですが、letに対してさらに制約をつけた変数宣言という位置づけになります。 基本的な使い方はletと同じですが、const再代入できない変数を定義するキーワードです。

varletでは、変数宣言と代入を別々に行うことができました。

// varやletで宣言した変数には代入できる
let bookTitle; // `undefined`で初期化される
bookTitle = "JavaScriptの本"; // 値を代入している

しかし、constでの宣言と代入を別々にはできないため、次のコードは構文エラー(SyntaxError)となります。

const bookTitle; // SyntaxError: missing = in const declaration
bookTitle = "JavaScriptの本";

constは必ず宣言時に値を指定しなければなりません。

const bookTitle = "JavaScriptの本";

そして、一度constで宣言された変数には再代入できなくなります。 そのため、次のコードではbookTitleを上書きしようとしてTypeErrorとなります。

const bookTitle = "JavaScriptの本";
bookTitle = "上書き"; // TypeError: invalid assignment to const `bookTitle'

一般的に変数への再代入は「変数の値は最初に定義した値と常に同じである」という参照透過性と呼ばれるルールを壊すため、 バグを発生させやすい要因として知られています。

変数に再代入をしたいケースとして、ループなどの反復処理の途中で値を変化させたい場合などがあります。 しかし、多くのケースで代替できる表現があるため、必ずしもvarletを使わなくても実現できます。 constを使うことでバグに気づきやすくなるため、constを積極的に利用していくことを推奨しています。

[コラム] constは定数ではない

constは「再代入できない変数」を定義する変数宣言であり、必ずしも定数を定義するわけではありません。 定数とは、一度定義した名前(変数名)が常に同じ値を示すものです。

JavaScriptでも、const宣言によって定数に近い変数を定義できます。 次のように、const宣言によって定義した変数を、変更できないプリミティブな値で初期化すれば、それは実質的に定数です。 プリミティブな値とは、数値や文字列などオブジェクト以外のデータです。(詳細は「データ型とリテラル」の章で解説します)

// TEN_NUMBERという変数は常に10という値を示す
const TEN_NUMBER = 10;

しかし、JavaScriptではオブジェクトなどもconst宣言できます。 次のコードのように、オブジェクトという値そのものは、初期化したあとでも変更できます。

// `const`でオブジェクトを定義している
const object = {
    key: "値"
};
// オブジェクトそのものは変更できてしまう
object.key = "新しい値";

このように、constで宣言した変数が常に同じ値と示すとは限らないため、定数とは呼べません。 (詳細は「オブジェクト」の章で解説します)

またconstには、変数名の命名規則はなく、代入できる値にも制限はありません。 そのため、const宣言の特性として「再代入できない変数」を定義すると理解しておくのがよいでしょう。

まとめ

JavaScriptにおける変数宣言としてvarletconstがあることについて学びました。

varはもっとも基礎的な変数宣言方法です。 letconstvarの問題を改善するためにES2015で導入されました。

varは殆どのケースでletconstに置き換えが可能です。 constは再代入できない変数を定義するキーワードです。 再代入を禁止することで、ミスから発生するバグを減らすことが期待できます。

そのためconstで変数を定義できないかを検討し、できない場合はletを使うことを推奨しています。