本記事では、プログラミング言語を問わず重要、且つ基礎的な内容である「変数」(および定数)について、詳しく説明していきます。
目次
変数とは
JavaScriptに限らず、全てのプログラミング言語には「変数」という概念があります。
プログラミングにおける「変数」を一文で簡潔に表現するならば、次のようになります。
この一文をしっかりと頭に入れた状態で、記事を読み進めていってください。
「変数」とは、情報を入れておくための容器である。
どんなプログラミング言語にも「変数」はあるので、書き方が異なるだけです。
本記事では、JavaScriptの変数について学んでいきます。
変数を作る(変数宣言)
プログラミング言語で、何か情報を入れる容器を作ることを「変数を宣言する」と言います。
では、試しに変数を宣言してみましょう。
例:「年齢」情報を入れておくための変数を宣言してください。
let age;
入れておく情報が「年齢」なので、変数の名前を「age」にしています。
このように、変数名は、その変数に入る情報を的確に表す英単語で命名することが重要です。

JavaScriptの学習を進める中で、「var」というキーワードを使って変数宣言しているコードを見かけることがあると思います。
これは2015年以前の文法で、以降はあまり推奨されません。世の中には2015年以前に作られたJavaScriptプログラムが現役で活躍しているため、「var」の存在を知っておく必要はあります。
ただし、これからプログラムされる際には、特別な理由がない限り変数宣言には「let」を使用してください。
変数に情報を入れる(代入/初期化)
変数に情報を入れることを、「代入」、あるいは「初期化」と言います。
変数の初期化
変数は、宣言と同時に情報を入れることができます。
それを「変数を初期化する」と言います。
では、試しに変数を初期化してみましょう。
例:「年齢」情報を入れておくための変数を宣言し、20という値で初期化してください。
let age = 20;
変数への代入
変数を宣言した行とは別の場所で情報を入れることもできます。
それを「変数に代入する」と言います。
変数に代入してみましょう。
let age;
age = 20;
宣言した変数に代入された値は、別の値に入れ替えることができます。
これを「再代入」と言います。
let age = 20; // 👈変数「age」に、二十歳として20を代入
age = 30; // 👈サバを読んでいたようで、30に再代入
console.log( age );
> 30
定数
変数は、「再代入」できるとお伝えしましたが、再代入を許可したくない場合もあります。
そんな時に役に立つのが「定数」です。
定数は、一度代入された値を変更することができません。
定数の宣言(および初期化)
定数を宣言する際には、「const」というキーワードを使用します。
また、定数の名前は一般的にすべて大文字のスネークケースで記述されます。
※ スネークケースが分からない方は、「命名規則」の記事をお読みいただくことをお勧めします。
また、重要なポイントとして、定数は宣言と同時に初期化する必要があります。
つまり、次のようなコードはNGです。
const MY_BIRTH; // 👈構文エラー!
定数を宣言したならば、その場で固定の値を代入するというルールをしっかりと覚えておいてください。
const MY_BIRTH = "1999/12/12"; // 👈宣言と初期化が同時に行われている!
そして、前述の通り、初期化された値は再代入できません。
const MY_BIRTH = "1999/12/12";
MY_BIRTH = "2000/12/12"; // 👈再代入してしまっている
console.log( MY_BIRTH );
👆このように書いてしまうと実行時にエラーになります。エラーメッセージは「定数に対して代入しているタイプエラー」という意味になります。
定数(const)の注意事項
constによって宣言した定数の「巻き上げ」
constキーワードによって宣言された定数は、「let」と同様に、宣言した位置よりも後ろでないとアクセスすることができず、アクセスした場合はエラーになります。
オブジェクトや配列の扱い
constキーワードによって宣言された定数の値が、オブジェクトや配列だった場合、全体を再代入することはできませんが、それらの要素に対する上書きや要素の追加は可能なので注意が必要です。
まずは、定数らしく「再代入ができない」パターンを2つ示します。
定数の値がオブジェクトの場合と、配列の場合です。
const x = {k: "v"};
// 👇オブジェクト全体を再代入しようとしている
x = {key: "val"};
// 👇エラーになる
console.log(x);
▶ Uncaught TypeError: Assignment to constant variable.
const x = [1, 2, 3];
// 👇配列全体を再代入しようとしている
x = [4, 5, 6];
// 👇エラーになる
console.log(x);
▶ Uncaught TypeError: Assignment to constant variable.
続いて、定数ですが「再代入できる」パターンを2つ示します。
定数の値がオブジェクトの場合と、配列の場合です。
const x = {k: "v"};
// kプロパティの値を再代入している
x.k = "val";
console.log(x);
▶ {k: 'val'}
const x = [1, 2, 3];
// インデックス 0 の値を再代入している
x[0] = 100;
console.log(x);
▶ (3) [100, 2, 3]
シャロ―イミュータビリティ(Shallow Immutability)
前述のように、constキーワードによって宣言された定数であっても、オブジェクトや配列だった場合、それらの要素に対する上書きや要素の追加は可能になることを、「シャロ―イミュータビリティ(Shallow Immutability)」あるいは「参照の不変性(Reference Immutability)」と呼ぶことがあります。
シャロ―イミュータビリティを解決するには、Object.freezeを使用する方法があります。
const person = Object.freeze({
name: 'Alice',
age: 25
});
person.age = 26; // 変更されない
console.log(person.age); // 25
しかし、Object.freezeを使用したとしても、配列の要素がオブジェクトである場合、そのオブジェクト自体は凍結されないため、プロパティの変更が可能になります。
この問題を解決するには、「深い凍結(Deep Freeze)」という手法が用いられます。
function deepFreeze(obj) {
Object.freeze(obj);
Object.keys(obj).forEach(key => {
if (typeof obj[key] === 'object' && obj[key] !== null) {
deepFreeze(obj[key]);
}
});
}
const people = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 }
];
deepFreeze(people);
people[0].age = 26; // 変更されない
console.log(people[0].age); // 25
people.push({ name: 'Charlie', age: 35 }); // 変更されない
console.log(people.length); // 2
👆上記のdeepFreeze関数は、オブジェクトや配列のすべてのネストされたプロパティを再帰的に凍結し、完全な不変性を実現しています。
オブジェクトが複雑にネストされると深い凍結(Deep Freeze)は手間がかかります。JavaScriptのオブジェクトや配列は柔軟であり、どこまでもネスト可能なので、すべての階層を凍結するのは現実的ではない場合もあります。
「変数」「定数」という名前の意味
文字通り、「変数」は変わる(変化する)数で、「定数」は定まった(固定の)数なのは想像がつくかと思います。
しかし、本記事で学習したように、変数にも定数にも、「文字列」を入れられますよね。
それなのに「数」というのは矛盾している、と感じられた方はいませんか?
実はこれには納得の理由があるのです。
コンピュータでの「文字」の扱い
いきなり結論から入りますが、コンピュータにとっては、文字も数値なのです。
コンピュータは、あらゆる情報を0と1の2種類の数値から成る2進数で表現します。
人間の目には文字に見える「a」でも、コンピュータから見れば「00001010」という二進数ですし、日本語などの全角文字や、記号にも二進数が割り当てられています。
例えば「あ」は「11100011 10000001 10000010」です。
これが、変数や定数に文字列を入れられても、名前に「数」が付いている理由です。
最後に
次に学習する記事としてオススメするのは、「JavaScriptのデータ型について」です。
本記事についての質問、誤りの指摘、ご意見ご感想などありましたら、ぜひコメント頂ければ幸いです。
最後までお読みいただき、ありがとうございました。


コメント