オブジェクトへプロパティの追加や値を変更を不可にする(freeze)

Object オブジェクトのメソッドである freeze メソッドを使うことで、オブジェクトへのプロパティの追加や削除を禁止することができます。また既存のプロパティの値を変更することもできなくなります。ここでは JavaScript でオブジェクトへのプロパティの追加を禁止したりプロパティの値の変更を変更できなくする方法について解説します。

(Last modified: )

プロパティの変更を禁止する(freeze)

オブジェクトに対する変更を禁止するには Object オブジェクトの freeze メソッドを使います。書式は次の通りです。

Object.freeze(オブジェクト)

メソッドを実行すると、引数に指定したオブジェクトに新しいプロパティを追加したり既存のプロパティを削除することができなくなります。また既存のプロパティの値を変更することもできなくなります。

次のサンプルをみてください。

const user = {
  name:'山田太郎', 
  age:32,
  address:'大阪府'
};

user.address = '東京都';
console.log(user);
>> {name: "山田太郎", age: 32, address: "東京都"}

const を使ってオブジェクトを変数に代入したとしても、新しいオブジェクトを同じ変数に代入することができないだけで、ミュータブル(変更可能)であるオブジェクトはプロパティの値をあとから変更することができます。

作成したオブジェクトのプロパティを変更不可とし、プロパティの追加やプロパティの値の変更ができなくするようにするには次のサンプルのように freeze メソッドの引数に対象となるオブジェクトを指定して呼び出します。

const user = {
  name:'山田太郎', 
  age:32,
  address:'大阪府'
};

Object.freeze(user);

user.address = '東京都'; // プロパティの値を変更する
console.log(user);
>> {name: "山田太郎", age: 32, address: "大阪府"}

オブジェクトのプロパティの値を変更してもエラーにはなりませんが、実際に変更は行われずに元の値のままです。

今度は freeze メソッドを呼び出したあと、新しいプロパティを追加と既存のプロパティの削除を行ってみます。

const user = {
  name:'山田太郎', 
  age:32,
  address:'大阪府'
};

Object.freeze(user);

user.hobby = '映画';  // 新しいプロパティの追加
delete user.age;  // 既存のプロパティの削除

console.log(user);
>> {name: "山田太郎", age: 32, address: "大阪府"}

新しいプロパティを追加したり既存のプロパティを削除してもエラーにはなりませんが、実際にはプロパティは追加されず既存のプロパティも削除されません。

このように freeze メソッドを使ってオブジェクトを変更不可にすることで、プロパティの値を変更したり新しいプロパティを追加することができなくなります。

なお strict モードを有効にした場合、変更不可にしたあとでプロパティの値を変更しようとしたり新しいプロパティを追加しようとするとエラーになります。

'use strict';

const user = {
  name:'山田太郎',
  age:32,
  address:'大阪府'
};

Object.freeze(user);

user.address = '東京都'; // プロパティの値を変更する
>> Uncaught TypeError: Cannot assign to read only property 'address' of object '#<Object>'

※ strict モードについては「Strictモードを有効にする」を参照されてください。

配列を変更不可にする

Object.freeze メソッドはオブジェクトだけではなく配列を引数に指定して呼び出すことができます。すると配列の要素の値を変更したり、新しい要素を追加することができなくなります。

次のサンプルをみてください。

const point = [48, 72, 65];

Object.freeze(point);

point[1] = 78;  // 要素を変更する
point[3] = 54;  // 要素を追加する

console.log(point);
>> [48, 72, 65]

配列の要素の値を変更したり新しい要素を追加してもエラーにはなりませんが、実際には要素の値は変更されず新しい要素も追加されていません。

プロパティの値がオブジェクトだった場合

freeze メソッドを呼び出すことで変更を不可にできるのは、メソッドの引数に指定したオブジェクトのプロパティのみが対象です。プロパティの値として別のオブジェクトや配列が格納されていた場合、子オブジェクトのプロパティは変更が行えます。

次のサンプルをみてください。

let user = {
  name:'山田太郎', 
  hobby:['Movie', 'Game']
};

Object.freeze(user);

user.name = 'Yamada Tarou';  // プロパティの値を変更する
user.hobby[0] = 'Sports';  // 子オブジェクト(配列)の要素の値を変更する

console.log(user.hobby);
>> ["Sports", "Game"]

オブジェクトを変更不可にしても、子オブジェクトのプロパティの値は変更することができました。

子オブジェクトも含めて変更不可にするには、子オブジェクトに対しても freeze メソッドを呼び出す必要があります。

let user = {
  name:'山田太郎', 
  hobby:['Movie', 'Game']
};

Object.freeze(user.hobby);
Object.freeze(user);

user.hobby[0] = 'Sports'; // 子オブジェクト(配列)の要素の値を変更する

console.log(user.hobby);
>> ["Movie", "Game"]

子オブジェクトのプロパティの値も変更不可にすることができました。

先ほどのサンプルでは対象となる子オブジェクトを明示的に指定して変更不可にしていますが、どのようなデータが含まれているか分からない場合に子オブジェクトも含めて変更不可にするには、プロパティの値を順に調べオブジェクトだった場合は変更不可にするといった処理を記述する必要があります。また子オブジェクトだけでなく孫オブジェクトなどが含まれる可能性がある場合は再帰的にオブジェクトが含まれているかどうか調べる必要があります。

-- --

JavaScript でオブジェクトへのプロパティの追加を禁止したりプロパティの値の変更を変更できなくする方法について解説しました。

( Written by Tatsuo Ikura )

プロフィール画像

著者 / TATSUO IKURA

これから IT 関連の知識を学ばれる方を対象に、色々な言語でのプログラミング方法や関連する技術、開発環境構築などに関する解説サイトを運営しています。