JavaScriptのAssignment to constant variableを直す方法|constとletの選び方
constへの再代入で出るTypeErrorを、カウンター・計算・配列の例で解説。letへ変える場合と、constを保って直す場合の判断、練習問題と模範解答を紹介します。
数を1増やしたいだけなのに、TypeError: Assignment to constant variable.で止まる。「計算式は合っていそうなのに」と悩んだら、計算結果を入れ直そうとした変数の宣言を見ます。
constで宣言した名前には、後から別の値を再代入できません。値が変わるカウンターならletへ直しますが、全部のconstを置き換える必要はありません。この記事では、エラーが出た場所から使い分けを考えます。
変数や代入の意味から確認したい場合は、JavaScriptの変数・型・計算が前提になります。
まずエラーが出る短い例を見る
次は、数を1増やして表示するつもりのコードです。
const count = 0;
count += 1;
console.log(count);
count += 1で、新しい値をcountへ入れ直そうとして止まります。ChromeやNode.jsでは、次のようなエラーになります。Firefoxなどでは文言が異なります。MDN:constへの無効な代入
TypeError: Assignment to constant variable.
+= 1は、この数値の例ではcount = count + 1と同じ計算です。右側で1を求めることはできても、左側のcountへ再代入できません。その後のconsole.logまで進まないので、数字が出ないのも同じ原因です。
値を変える予定ならletを使う
カウンターは、0、1、2と変化する値です。宣言をletへ直します。
let count = 0;
count += 1;
console.log(count); // 1
宣言は名前を作ること、代入は値をその名前へ結び付けることです。宣言した後で値を入れ直す操作を、再代入と呼びます。
| 宣言 | 再代入 | 今回の使いどころ |
|---|---|---|
const |
できない | 途中で入れ替えない値 |
let |
できる | 回数や残り時間など、変わる値 |
count++やcount -= 1も、countの値を更新します。=だけを検索しても見逃すので、エラー行の名前を確かめ、宣言した場所まで戻ってください。
constのまま、計算の組み立てを直せる場合もある
次は商品の合計に送料を足す例です。
const total = 500 * 3;
total = total + 100; // 再代入でエラー
最終結果だけが欲しいなら、途中の金額と送料込みの金額を別の名前にできます。
const price = 500;
const quantity = 3;
const shipping = 100;
const subtotal = price * quantity;
const total = subtotal + shipping;
console.log(total); // 1600
subtotalは商品だけの小計、totalは送料を含む合計です。どちらも再代入していません。計算の意味も読みやすくなりました。
反対に、ボタンを押すたびに数量を変えるなら、その数量にはletが合います。「この値は途中で変わるか」「別の意味の結果を同じ名前へ入れていないか」で判断してみてください。
constの配列は、なぜpushできるのか
ここが少しややこしいところです。次の配列への追加はできます。
const items = ["ノート", "ペン"];
items.push("付せん");
console.log(items.length); // 3
constが固定するのは、名前と値の結び付きです。itemsが同じ配列を参照したまま、その配列の要素を変更することまでは禁止しません。参照は、ここでは「どの配列を使っているかを示すもの」と考えてください。MDN:const
一方、別の配列への入れ替えは再代入です。
const items = ["ノート", "ペン"];
items = ["付せん"]; // エラー
オブジェクトも同じです。
const player = { name: "Aoi", score: 0 };
player.score = 10; // 同じオブジェクトの項目を変更
console.log(player.score); // 10
player = { name: "Aoi", score: 10 };と書けば、今度は別のオブジェクトへの再代入になります。配列やオブジェクトを完全に変更禁止にしたい場合は、constだけでは足りません。
よく似た別のエラーを区別する
コンソールで何度もコードを試すと、別のエラーが混ざることがあります。
| コードや状況 | 問題 |
|---|---|
const count = 0; count = 1; |
再代入によるTypeError |
同じスコープでconst countをもう一度宣言 |
再宣言によるSyntaxError |
普通の宣言でconst count;とだけ書く |
初期値がなくSyntaxError |
スコープは、同じ名前を参照できる範囲です。例えば{ ... }で囲んだブロックは、その範囲を作ります。同名の別変数がある大きなコードでは、エラー行から見える方の宣言を確認します。
練習コードは1例ずつ別に実行してください。コンソールに前の宣言が残って混乱したら、ページを再読み込みしてから試すと整理できます。letへ変えれば何でも直る、とは覚えない方が後で助かります。
練習:変わる値だけをletにする
次のコードを、10点加算して表示できるように直してください。プレイヤー名は途中で変更しません。あわせて、最後の配列への追加も直す必要があるか考えます。
const playerName = "Aoi";
const score = 0;
const results = [];
score += 10;
results.push(score);
console.log(`${playerName}: ${score}点`);
模範解答
const playerName = "Aoi";
let score = 0;
const results = [];
score += 10;
results.push(score);
console.log(`${playerName}: ${score}点`);
console.log(results.length);
Aoi: 10点
1
解説
再代入するのはscoreなので、その宣言をletへ変えます。playerNameは変わらず、results.push(score)は同じ配列への追加なので、残り2つはconstのままです。
エラーが消えたら、期待する点数と配列の要素数も確かめます。「止まらなくなった」と「欲しい結果になった」の両方を見る習慣を付けましょう。