【JS】constで定義したオブジェクトや配列は、中身を変更できてしまう
動機
普段は React を使って小規模アプリの開発を行いながら、JavaScript についての理解を深めるために勉強しております。その一環として、以下のサイトを利用しながら学習内容を復習しています。また、学んだことを定期的にアウトプットしていくことで、知識の定着を図ろうと目論んでおります!
第一弾は、const
で定義したオブジェクトや配列の挙動について、メモ程度にアウトプットしたいと思います。
JavaScript の const で定義した変数は必ずしも不変ではない
JavaScript では、var
、let
、const
の 3 種類の変数宣言がありますが、const
は一般的に定数を宣言する際に使用されます。ですが、const
で定義された変数が必ずしも完全に不変であるわけではありません。特に、const
で宣言されたオブジェクトや配列の場合、その変数自体の再代入はできませんが、オブジェクトのプロパティや配列の要素は変更することが可能です。
この挙動は、const
が変数への参照自体の不変性を保証する一方で、参照先のデータ(オブジェクトや配列の中身)の不変性までは保証しないために起こります。つまり、const
で宣言されたオブジェクトや配列の参照を変更することはできませんが、その中身(プロパティや要素)の変更は可能ということです。この理解は、JavaScript を使用する際に変数の不変性を正しく扱うために重要になります。
const で定義したオブジェクトや配列は、中身を変更できてしまう
では、早速コードを書いて確認してみましょう。
まずは、オブジェクトのケースになります。
const obj = {
name: "Bob",
age: 30,
};
obj.name = "Mike";
console.log(obj);
// {name: "Mike", age: 30}
上記のコードでは、obj をconst
で定義し、次に、obj の name を更新しています。
その後に、obj の中身を出力をすると、name が Bob から Mike に変更されてしまっています。
配列も同様に、配列のプロパティの値が変更できてしまいます。
const nameArray = ["Bob", "Mike"];
nameArray[0] = "Ken";
console.log(nameArray);
// ["Ken", "Mike"]
懸念点
const
で宣言されたとしても、オブジェクトや配列の中身を変更することができるため、プロパティの意図しない変更が起こり、それがバグの原因になることがあります。
さらに、const
が指し示すのは変数の再代入を防ぐことであり、その変数が参照するオブジェクトや配列の内容が変更不可能であるとは限らないため、コードの可読性に影響を及ぼす可能性もあります。
これにより、オブジェクトや配列が読み取り専用であるかどうかが一見で判断しにくくなり、コードの理解やメンテナンスが困難になる場合があります。
回避策
回避策として、Object.freeze
を利用し、オブジェクトや配列を凍結させ、オブジェクトや配列のプロパティの追加や変更を阻止します。(注意点として、strict mode
にしておく必要があります。)
// オブジェクトのケース
const obj = Object.freeze({
name: "Bob",
age: 30,
});
obj.name = "Mike"; // Cannot assign to name because it is a read-only property.
// 配列のケース
const nameArray = Object.freeze(["Bob", "Mike"]);
nameArray[0] = "Ken"; // Index signature in type readonly string[] only permits reading.
こうすることで、意図しないプロパティの追加や変更によるバグを防ぐことができ、可読性も上がります。
まとめ
個人で開発している際に、Object.freeze
を使用してこなかったのですが、これを機に使ってみようと思います。
JavaScript は意外な落とし穴が結構存在していそうなので、引き続き復習し、記事にしていきます。
このような積み上げをしていくと、可読性が高く、バグのリスクを減らすコードを書けるエンジニアになれると信じて学んでいきます!!
参考にしたサイト
Discussion