概要
JavaScriptにおいて、定数(const)で定義したオブジェクトであっても、そのプロパティの内容は自由に変更可能です。しかし、アプリケーションの設定値やシステムの基本情報など、プログラム実行中に一切の書き換えを許容したくない場面が存在します。本記事では、オブジェクトを「凍結」し、プロパティの追加・削除・変更を物理的に不可能にする Object.freeze メソッドの実装方法を解説します。
仕様(入出力)
| メソッド | 意味 | 戻り値 |
Object.freeze() | オブジェクトを凍結します。既存プロパティの変更、削除、新しいプロパティの追加を禁止します。 | 凍結されたオブジェクト自身 |
Object.isFrozen() | 指定したオブジェクトが凍結されているかどうかを判定します。 | 凍結されていれば true、そうでなければ false |
基本の使い方
Object.freeze を実行すると、そのオブジェクトは読み取り専用となります。非厳格モード(Strict Mode以外)では変更操作は単に無視されますが、モダンな開発における strict mode 環境下では、変更を試みた瞬間に TypeError が発生し、バグの早期発見につながります。
コード全文(HTML / JAVASCRIPT)
HTML
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Cloud Environment Guard</title>
</head>
<body>
<div id="config-manager">
<h2>環境設定マネージャー</h2>
<div id="log-output"></div>
<hr>
<button id="update-attempt">設定の書き換えを試行</button>
<button id="check-status">凍結状態を確認</button>
</div>
<script type="module" src="main.js"></script>
</body>
</html>
JavaScript
'use strict';
/**
* システムの環境設定オブジェクト
* シナリオ:クラウドサーバーの接続設定
*/
const systemConfig = {
endpoint: "https://api.v3.internal.service",
retryLimit: 5,
adminUser: "mori"
};
// オブジェクトを凍結
Object.freeze(systemConfig);
const logOutput = document.getElementById('log-output');
/**
* 処理結果を画面に表示する
* @param {string} message
*/
const printLog = (message) => {
const p = document.createElement('p');
p.textContent = message;
logOutput.appendChild(p);
};
// 1. 書き換え試行時の挙動
document.getElementById('update-attempt').addEventListener('click', () => {
try {
printLog("値を変更しようとしています...");
// 凍結されているため、エラーが発生する
systemConfig.retryLimit = 10;
systemConfig.newOption = "enabled";
} catch (error) {
printLog(`エラーを検知: ${error.message}`);
console.error("書き換えがブロックされました:", error);
}
});
// 2. 状態判定メソッドの利用
document.getElementById('check-status').addEventListener('click', () => {
const isFrozen = Object.isFrozen(systemConfig);
printLog(`このオブジェクトの凍結状態: ${isFrozen}`);
});
printLog(`初期管理者: ${systemConfig.adminUser}`);
カスタムポイント
- 設定オブジェクトだけでなく、固定された選択肢を持つ「列挙型(Enum)」の代わりとしてこのメソッドを適用してください。
- 大規模なアプリケーションでは、データの初期化が完了した直後に
Object.freezeを呼び出し、以後の意図しない副作用を排除するガード節として機能させてください。
注意点
Object.freezeは「浅い凍結(Shallow Freeze)」です。オブジェクトのプロパティがさらに別のオブジェクトを持っている場合、その子オブジェクトの中身までは凍結されません。- 一度凍結したオブジェクトを「解凍」する手段はJavaScriptには用意されていません。必要に応じてオブジェクトをコピーした新しい変数を作成する必要があります。
- 凍結されたオブジェクトへの操作は、
strict modeが無効な環境では静かに失敗し、エラーを投げないため、必ず'use strict';を併用して挙動を可視化してください。
応用
配列に対しても Object.freeze を適用することが可能です。これにより、push や pop といった破壊的なメソッドによる配列の書き換えを防止できます。
'use strict';
/**
* 変更不可なステータスリスト
*/
const baseLevels = [1, 5, 10];
Object.freeze(baseLevels);
try {
// 凍結されているため、要素の追加は失敗する
baseLevels.push(20);
} catch (e) {
console.log("配列の更新が禁止されています。");
}
console.log(baseLevels); // [1, 5, 10]
まとめ
Object.freeze は、JavaScriptにおけるデータの堅牢性を高めるために非常に重要な役割を果たします。単なる定数定義では防げないプロパティの改ざんや破壊的な変更を、言語レベルの制約として封じ込めることが可能です。特に共有ライブラリの開発や、チーム開発における共通定数の定義において、変更されるべきではないデータを明示的に保護する手段として推奨されます。Object.isFrozen による状態確認と組み合わせることで、データの整合性をより確実に維持する設計が実現可能です。
