本記事では、JavaScript の const キーワードを使用して定数を定義する方法について解説します。
JavaScriptのconstキーワードについて
ES6では、constキーワードを使った新しい定数宣言の方法が用意されています。
const キーワードは、値への読み取り専用の参照を作成します。
const 定数名 = 値;
慣例により、定数識別子は大文字で表記されます。
letキーワードと同様に、constキーワードはブロックスコープの変数を宣言します。ただし、constキーワードで宣言したブロックスコープの変数は、再代入できません。
letキーワードで宣言された変数は、mutableです。つまり、次の例に示すように、いつでも好きなときにその値を変更することができます。
let num = 30;
num = 10;
num = num + 5;
console.log(num); // 15
しかし、constキーワードで作成された変数は「不変」です。つまり、異なる値に再代入することはできません。
constキーワードで宣言された変数を再代入しようとすると、次のようなTypeErrorが発生します。
const NUMBER = 1;
NUMBER = 2; // TypeError
letキーワードとは異なり、constキーワードで宣言された変数に値を初期化する必要があります。
次の例では、const 変数宣言にイニシャライザーがないため、SyntaxError が発生します。
const COLOR; // SyntaxError
JavaScript の const とオブジェクト
const キーワードは、作成する変数が読み取り専用であることを保証します。しかし、const変数が参照する実際の値が不変であることを意味するものではありません。
const person = { age: 30 };
person.age = 20; // これはOK
console.log(person.age); // 20
person変数が定数であっても、そのプロパティの値を変更することはできます。
ただし、以下のようにperson定数に別の値を代入し直すことはできません。
person = { age: 10 }; // オブジェクト丸ごと代入するとエラーになる
personオブジェクトの値をイミュータブルにしたい場合は、Object.freeze()メソッドでフリーズさせる必要があります。
const person = Object.freeze({age: 30});
person.age = 20; // TypeError
Object.freeze()は浅いので、オブジェクトのプロパティをフリーズさせることができますが、プロパティから参照されるオブジェクトをフリーズさせることはできないことに注意しましょう。
例えば、companyオブジェクトは一定で凍結されます。
const company = Object.freeze({
name: 'Code Marine',
address: {
city: 'Tokyo',
zipcode: 23938
}
});
しかし、company.addressオブジェクトはimmutableではないので、以下のように新しいプロパティをcompany.addressオブジェクトに追加します。
company.address.country = 'Japan'; // OK
JavaScriptのconstと配列
const colors = ['赤'];
colors.push('青');
console.log(colors); // ["赤", "青"]
colors.pop();
colors.pop();
console.log(colors); // []
colors = []; // エラー
この例では、const キーワードを使用して、1 つの要素を持つ配列 colors を宣言しています。そして、緑色を追加することで、配列の要素を変更することができます。しかし、配列colorsを別の配列に再代入することはできません。
JavaScriptのconstをforループで使用する
ES6では、配列、マップ、セットなどの反復可能なオブジェクトを反復するループを作成するためのfor…ofという新しいコンストラクトが提供されています。
let scores = [25, 50, 75];
for (let number of numbers) {
console.log(number);
}
ループの中で変数numberを変更するつもりがない場合は、代わりにconstキーワードを使うことができます。
let scores = [75, 80, 95];
for (const number of numbers) {
console.log(number);
}
この例では、for…ofはループの反復ごとにconstキーワードの新しいバインディングを作成します。言い換えれば、「各反復で新しいnumber定数が作成される」ということです。
constは命令形のforループでは機能しないことに注意してください。
命令形のforループでconstキーワードを使って変数を宣言しようとすると、TypeErrorが発生します。
for (const i = 0; i < numbers.length; i++) { // エラー
console.log(number[i]);
}
なぜなら、この宣言はループ本体が始まる前に一度だけ評価されるからです。