🧊

【JS】constで定義したオブジェクトや配列は、中身を変更できてしまう

2023/11/14に公開

動機

普段は React を使って小規模アプリの開発を行いながら、JavaScript についての理解を深めるために勉強しております。その一環として、以下のサイトを利用しながら学習内容を復習しています。また、学んだことを定期的にアウトプットしていくことで、知識の定着を図ろうと目論んでおります!

https://jsprimer.net/basic/

第一弾は、const で定義したオブジェクトや配列の挙動について、メモ程度にアウトプットしたいと思います。

JavaScript の const で定義した変数は必ずしも不変ではない

JavaScript では、varletconstの 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 は意外な落とし穴が結構存在していそうなので、引き続き復習し、記事にしていきます。

このような積み上げをしていくと、可読性が高く、バグのリスクを減らすコードを書けるエンジニアになれると信じて学んでいきます!!

参考にしたサイト

https://jsprimer.net/basic/

GitHubで編集を提案

Discussion