Javascript の変数の話

記事
IT・テクノロジー

Javascript の変数の話

Javascript に限らず、プログラミング言語には変数という概念があります。プログラムで扱うデータを入れる場所です。最新の Javascript では3種類の変数を利用する事ができます。

* const
* let
* var
です。constとletは後から導入された物ですが、基本的にはこの2つを利用することが推奨されています。理由は、なるべくバグを出さないようにするためというのが大きいと思います。

どうして、constやletを使うとバグを生み出し易いのかご存知ですか?この記事では Javascript での変数について書いてみました。

varだけでプログラムは書けます!

当たり前ですが、varだけでもプログラムは書けます。慎重にコードを書けば別にvarを使う事自体は問題ないのですが、少し大きなプログラム、特に後から手直ししたりする場合にバグの原因になるのでconstやletを使うことが推奨されています。

幾つか理由がありますが、var の問題は大きいものが2点です

同じ名前の変数を複数宣言できる
変数の宣言前の参照も許されている(値はundefined)
ESLint などプログラムをチェックするプログラムを使えば、「危ない」コードは見つけてくれます。そうした仕組みを上手く利用する場合は、大きな問題ではないのですが、こうした、仕組みを利用しない場合バグの原因になり易いので、letやconstが導入されました。

それでも、verが残されているのは、互換性のためなので、新しくプログラムを書く際には基本的には「var」は使わないのがいちばんです!

バグの少ないプログラムには、「const」と「let」を使う
バグの少ないプログラムにするためにには、基本的に「const」を使って、constが使えない場合は「let」を使うようにすると考えるとシンプルです。

constとletの違いは、変数に再代入(値の更新)ができるか、できないかの違いです。

constの場合は、値を入れた後再び別の値を入れることができません。letの場合は、値を上書きする事ができます。

もう一つ大切なことは、変数を宣言する場所です。実はこれが結構重要です。 変数には「スコープ(scope)」という概念があります。簡単にいうと、変数が有効な範囲があります。

別の例で言うと、「ドル」と言う通貨があります。皆さんよくご存知ですよね? 有名なのは「アメリカのドル」ですが、実はカナダでも「ドル」と言う通貨を使っていて、「カナダドル」と呼ばれています。もちん、「ドル」と言う名前だけが同じで全く別の通貨で価値も違います。

変数にも似た概念があって、変数が通用する範囲が決まっています。例えば、別の関数の中で同じ名前の変数を使っても、全く別のものとして扱われます。関数はわかり易いのですが、例えばループなどの「ブロック」単位での範囲もあります。

文章だとわかりにくいのでサンプルの例をあげると

const samples = [10, 20, 30, 40];
let total = 0;

for (let i = 0; i < samples.length; i++) {
  const value = samples[i];
  lotal += value;
}
console.log(total);

// console.log(value);


「sample」は、配列で4つの数字が入っています。この値は再代入しないので「const」で定義しています。もう一つの変数「total」は、sample の数の合計を入れるので、最初は「0」に初期化しています。その後の、for ループで配列の値を一つづつ取り出して合計を加えていくので再代入が必要になります。したがって、「let」で定義しています。

「sample」と「total」は、for ループの外で定義されているので、for ループを抜けた後でも三勝可能です。(変数が有効)ところが、「value」は for ループの中で定義されているので、for ループの外では無効になります。したがって、コメントアウトしてありますが、ループの外で「console.log(value)」のように参照しようとするとエラーになります。

もう一つ、よくある勘違いですが、for ループの「value」は「const」で定義しています。これはループの中で値が変わると思って「const」ではダメだと思う方も多いようですが、ループの中で再代入をしないので「const」を使う事ができます。

もっと正確に言うと、この変数のメモリは、各ループの実行の際に確保されて1回のループの実行が終わると無効になるように扱われます。したがって、ループ内で値を再代入しなければ「const」が使えるというわけです。

できるだけ、constを使う理由は、不必要な再代入によるバグをなくすためです。変更しない値ならば、constを使った方が、意図しない代入はエラーになるので間違いを見つけることができるからです。

constは定数?

「constは再代入できない」これが Javascript での定義です。再代入できないから値が一定とは限りません。どう言うことかというと、例えば配列やオブジェクトの場合は、ちょっと事情が変わってくるからです。

C 言語や C++を利用した事がある方は、ご存知だと思いますが、配列(array)やオブジェクト(object)の場合は、変数の値は「ポインタ」で、配列やオブジェクトの最初のデータの場所(アドレス:address)を指しているからです。これも、ちょっとわかりづらいですよね?

簡単に言うと、配列やオブジェクトは「複数」のデータを入れる入れ物のような物です。その変数は入れ物を指していて、入れ物の中身は何だかわからないと言う感じになっています。

つまり、入れ物は帰ることができませんが(再代入ができない)、入れ物の中身は入れ替えることができると言う事です。例えるならば、箱があって最初は空で後からりんごを入れると言う感じですが、箱は同じものというイメージです。りんごを取り出して、みかんを入れることもできますが、箱は同じままならば「const」が使えます。

これも例を使った方がわかり易いので以下のコードをみてください。

const values = [];
for (let i = 0 ; i <= 100 ; i++) {
    values.push(i);
}
console.log(values);

// values = [] <= エラーになります
配列で、「values」をconstとして定義しています。最初は空の配列です。 これをループで0から100までを順番に追加しています。

こうした使い方ならば、「const」で OK です。 オブジェクトの場合は、例えば名前、誕生日、体重を入れたオブジェクト「person」をconstで宣言して、後から体重のデータを更新するのは問題ありません。これも、「person」の場所は同じだからです。(箱は同じ)

const person = {
  name: "John",
  birthday: "2021-03-17",
  weight: 3,
};
person.weight = 3.2;
なので、ほとんどの配列はオブジェクトは「const」で良いことになります。

React のステートを使う場合は注意が必要
便利ですが、React でステートを使う場合や Redux で配列やオブジェクトを使う場合は注意が必要です。

React の場合、データが変更された部分のみを書き換えるという事をやって、描画(レンダリング)を最小限にしています。しかし、React の場合、配列やオブジェクトの中身を更新した場合、変更がわからない仕様になっています。(immutable と呼ばれています。)

そこで、配列やオブジェクトを変更する際は、配列やオブジェクトのコピーを作っておいて、コピーのデータを変更して、変更後にステートや Redux で管理している配列やオブジェクトに再代入するような処理が必要です。(つまり箱を取り替える) こうすることで、React に変更が認識されて画面を正しく更新することができます。

Vue の場合は、配列やオブジェクトの変更も検出できます。(mutable)

こうした、実装は言語ごと、フレームワークごとに違うので特に、文字列や配列、オブジェクトを扱う場合は、使用している言語やフレームワークの仕様を知っておく必要があります。’

まとめ
Javascript だけではありませんが、変数の扱い方がプログラミング言語ごとに違います。 変数の上書き(再代入)の制限やスコープ(有効範囲)、イミュータブルかミュータブルかなどは言語によって違うので注意が必要です。

Javascript の場合は、C/C++のようなポインタの概念はありませんが、配列やオブジェクトの場合、リファレンスなどと呼ばれていますが、実際は C/C++と似た扱われ方をしています。 したがって、データを格納している配列やオブジェクトを入れ替えなければ「const(定数)」として扱うことが許されています。こうした、データの場合、データに変更を加える場合、イミュータブルかミュータブルの扱いなのかを理解していないとバグの原因になります。

変数は、プログラムを学習する場合最初に学習する項目の一つですが、意外に奥が深くプログラミング言語をよく理解していないとバグの原因になる部分でもあります。

一通りプログラムを学習したら今一度、見直しておくと理解が深まるエリアです。
サービス数40万件のスキルマーケット、あなたにぴったりのサービスを探す