FJCT_ニフクラ mobile backend(mBaaS)お役立ちブログ

スマホアプリ開発にニフクラ mobile backend(mBaaS)。アプリ開発に役立つ情報をおとどけ!

JavaScriptの基本(その1)「var/let/constの違い」

JavaScriptはプログラマーの人気1位の言語と言われています。ブラウザで唯一動作が保証されているプログラミング言語ですし、サーバーサイドではNode.jsとして動作します。さまざまな分野で使われているプログラミング言語、それがJavaScriptです。

1つのプログラミングを習得すれば、他のプログラミング言語の学習も容易になります。まずJavaScriptをしっかりと学んでみましょう。

この記事ではそんなJavaScriptを学ぶ上で良くある疑問を、なるべく分かりやすく解説します。今回は「var/let/constの違い」について解説します。

変数の定義法の違い

varやlet、constはすべてJavaScriptで変数を定義する際に使われます。つまり、以下のような形です。

var a = 1;
let b = 2;
const c = 3;

console.log(a + b + c);
// => 6

エラーから見る違い

一見するとvarとlet、constに違いはなさそうです。しかし、以下に違いが出ます。まずvarを使った方法です。特にエラーは出ません。

var a = 1;
var a = 2; // 定義し直し

console.log(a);
// => 2

次にletを使った場合です。 a はすでに定義されていますというエラーが出ます。

let a = 1;
let a = 2;
// Uncaught SyntaxError: Identifier 'a' has already been declared

しかし、以下のように実行するとエラーは出ません。上の内容との違いは、a再定義しない 点にあります。最初に定義した a を再利用しています。

let a = 1;
a = 2; // letは外す

console.log(a);
// => 2

constの場合はどうでしょうか。以下はエラーになります。つまり再定義できません。

const a = 1;
const a = 2;
// Uncaught SyntaxError: Identifier 'a' has already been declared

ではletと同じようにしてみます。これもエラーになります。つまり再利用もできません。

const a = 1;
a = 2;
// Uncaught TypeError: Assignment to constant variable.

まとめると以下のようになります。

定義方法 再定義 再利用
var
let ×
const × ×

これが var 、 let 、 const の基本的な違いです。

varで定義するのは良くないのか

ここで1つの疑問がわくかも知れません。それは、すべてvarで良いのではないかということです。つまりletやconstではエラーが出てしまう場合でも、varならエラーが出ずに済みです。

元々JavaScriptではvarしかありませんでした。この時の問題として、どこかで変数が書き換えられてしまう可能性が存在しました。

チーム内で開発している場合、Aさんが url という変数を定義したとします。そして、Bさんも別なファイルで url という変数を定義したとします。これはエラーになりません。そして、CさんがAさんの用意した url を使おうとします。すると、内容が期待していたものと違っています。これはBさんの定義した url によって内容が上書きされてしまったために起きたことです。

これは別ファイルに限らず発生する可能性があります。変数の内容が保証されないのは、不具合につながりやすくなります。

同様のことは let でも言えます。すべての変数をletで定義すると、上書きされる可能性を残したままになります。どうしても必要ではない限りはconstを使うべきでしょう。

constは変数をまるごと入れ替えられないだけ

ここで注意点です。constであっても、変数の内容を書き換えることはできます。以下のコードはエラーになりません。

const a = {
    a: 'b',
    c: 'd',
};

a.a = 'e';

console.log(a.a);
// => e

constは変数の再定義を防ぎ、 変数をまるっと入れ替える ことはできません。しかし、上記の例のように一部だけの更新はできます。

つまり、以下はエラーになります。

const a = {
    a: 'b',
    c: 'd',
};

a = {
    a: 'e', // ← 変更
    c: 'd',
};
// Uncaught TypeError: Assignment to constant variable.

スコープが違えば、再定義可能

constを使ったとしても、その変数名はアプリケーション全体でユニーク(唯一一つ)というわけではありません。たとえば、以下のコードはエラーになりません。

const a = 1;

{
    const a = 2;
    console.log(a);
    // => 2
}

console.log(a);
// => 1

これは、波括弧によって変数のスコープ(有効範囲)が区切られているからです。以下のコードは最初の console.log(a); のところでエラーになってしまいます。 a が定義される前に呼び出されてしまっているためです。

const a = 1;

{
    console.log(a);
    // Cannot access 'a' before initialization
    const a = 2;
    console.log(a);
}

console.log(a);

しかし、以下の場合はエラーになりません。波括弧内で a が定義されていないため、最初の a が有効になっているためです。

const a = 1;

{
    console.log(a);
    // => 1
}

console.log(a);
// => 1

今回は簡単に波括弧を使いましたが、関数でも同様です。以下の場合は、両方とも1を出力します。

const a = 1;

function b() {
    console.log(a);
    // => 1
}

b();
console.log(a);
// => 1

以下の場合は1と2を出力します。

const a = 1;

function b() {
    const a = 2;
    console.log(a);
    // => 2
}

b();
console.log(a);
// => 1

このように変数のスコープは常に意識する必要があります。

letをなるべく使わないように書くには

letを使いたくなる場面としては、たとえば以下のような処理があります。下記のように書くと、abtrue の場合は1 、 false の場合は2となります。

let a = 1; // 初期値
if (b) {
    a = 2;
}

これを三項演算子を使って書くと、次のようになります。三項演算子は 条件 ? 条件がtrueの場合 : 条件がfalseの場合 という書き方になります。

const a = b ? 1 : 2;

もう一つは非同期処理が伴う場合です。以下のように書くと、ネットワーク処理が終わった後は data にデータが入ってきます。

let data;
fetch('/get')
    .then((res) => {
        return res.json();
    })
    .then((json) => {
        data = json
    });

これはasync/awaitで書くと次のようになります。letは使わずに済みます。

const res = await fetch('/get');
const data = await res.json();

このように書き方を工夫することで let ではなく const で書けます。そうなると、どうしてもletでないと難しいという場面はごく限られたものになりますし、そもそもvarは使わずにコーディングできるでしょう。

var/let/constを使わない場合

もしvarやlet、constを使わずに変数を定義するとどうなるでしょう。これは var がデフォルトで使われます。

a = 1;
a = 2;

console.log(a);
// => 2

var を使わないように、変数を定義する際にはきちんと const や let を頭に付けるようにしましょう。

まとめ

今回はvar/let/constの違いについて紹介しました。利用するお勧めはconstが一番、次にどうしても必要な場合はlet、そしてvarは使わないようにしましょう。

作ったアプリケーションが不具合を起こしたり、予期せぬ挙動に悩まされないよう変数の定義に気をつけてプログラミングしてください。

中津川 篤司

中津川 篤司

NCMBエヴァンジェリスト。プログラマ、エンジニアとしていくつかの企業で働き、28歳のときに独立。 2004年、まだ情報が少なかったオープンソースソフトの技術ブログ「MOONGIFT」を開設し、毎日情報を発信している。2013年に法人化、ビジネスとエンジニアを結ぶDXエージェンシー「DevRel」活動をスタート。