const で宣言した変数に、もう一度代入したときに出ます。
const count = 1;
count = 2;直し方は2つです。入れ直すなら let、入れ直さないなら中身を変えます。
const list = [1, 2];
list = [3];const が固定しているもの
const が固定するのは名前と値の結びつきで、値そのものではありません。
配列やオブジェクトなら、中身は変えられます。
エラーになりません。 list が指している配列は同じままで、その中身を変えただけだからです。
一方、丸ごと別のものに差し替えると落ちます。
for (const i = 0; i < 2; i++) {
console.log(i);
}| やること | const で |
|---|---|
x = 別の値 |
エラー |
x.prop = 値 |
できる |
x.push(値) |
できる |
x[0] = 値 |
できる |
中身も変えたくないなら
Object.freeze() で凍結します。
const result = null;
if (true) {
result = '見つかった';
}代入は無視されただけで、エラーは出ていません。 気づかないまま「設定が反映されない」ことになります。
'use strict' の中なら、はっきり落ちます。
文言が違うことに注意してください。 こちらは Assignment to constant variable. ではありません。
import/exportのあるファイル(モジュール)は、書かなくても strict モードです。 実務では落ちるほうが普通だと思ってください。
Object.freeze() が固めるのは1段だけです。中の入れ子は凍りません。
原因: for の書き方
1回だけ回って落ちます。 i++ が代入だからです。
for...of なら const で書けます。繰り返しごとに新しく作られるので、代入になりません。
| 書き方 | const |
|---|---|
for (let i = 0; ...) |
使えない。let を使う |
for (const x of ...) |
使える |
for (const k in ...) |
使える |
原因: あとで入れるつもりだった
あとから入れるなら let です。 ただ、多くの場合は書き換えずに済みます。
入れ直さない形に書けるなら、そのほうが安全です。 どこで値が変わったか探さなくて済みます。
似ているエラーとの違い
| 文言 | いつ出るか |
|---|---|
Assignment to constant variable. |
const の変数に代入した |
Cannot assign to read only property 'x' of ... |
凍結したオブジェクトの中身に代入した(strict) |
Cannot access 'x' before initialization |
宣言より前で使った → 別ページ |
x is not defined |
そもそも宣言していない |
このページの実行結果は Node 22.22.3 のものです。文言は処理系と版によって変わります。自分の環境で出た文言で検索してください。
探しかたの順序
- エラーの行で代入している変数名を見る
- その変数の宣言を探す。
constになっているはず - 入れ直す必要が本当にあるか考える
- ある →
letにする - ない → 中身を変えるか、三項演算子で1回で決める
- ある →
まとめ
constが固定するのは結びつき。値の中身ではない- 配列やオブジェクトの中身は変えられる
- 中身も守るなら
Object.freeze()。ただし黙って無視される(strict なら例外) for (const i = 0; ...)は書けない。for...ofなら書ける- 入れ直さない形にできるなら、そのほうがよい
const にした配列やオブジェクトの中身を、元に影響させずに変えたいときは、複製のしかたを知っておくと早く済みます。
→ オブジェクトを結合する