JavaScript
 Computer >> コンピューター >  >> プログラミング >> JavaScript

JavaScriptでオブジェクトの変更を防ぐ3つの方法(preventExtensions・seal・freeze)


ECMAScript 5では、オブジェクトの変更を防ぐためのメソッドが複数導入されました。これらの防止策を活用すれば、意図的か偶発的かに関わらず、誰もオブジェクトの機能や構造を勝手に書き換えられないようにできます。

変更防止メソッドには3つのレベルがある

JavaScriptのオブジェクト保護には、制限の強さが異なる3段階のメソッドが用意されています。それぞれの違いを表にまとめると以下の通りです。

操作preventExtensionssealfreeze
新規プロパティの追加
既存プロパティの値変更
既存プロパティの削除
既存プロパティの読み取り

1)preventExtensions:プロパティの追加を防ぐ

このレベルでは、新しいプロパティやメソッドを追加できなくなります。その一方で、既存のプロパティやメソッドへのアクセスは引き続き可能で、削除も行えます。このタスクを実現するのが Object.preventExtensions() メソッドであり、以後そのオブジェクトに新しいプロパティが追加されるのを防ぎます。

サンプルコード

<html>
<body>
<script>
   var object1 = {
      prop1: 1
   };
   Object.preventExtensions(object1);
   delete object1.prop1 // 既存プロパティは削除できる
   try {
      Object.defineProperty(object1, 'prop2', {
      value: 2
   });
   } catch (err) {
   document.write(err);
   }
   document.write("</br>");
   document.write(object1.prop1);
</script>
</body>
</html>

実行結果

TypeError: Cannot define property prop2, object is not extensible
undefined // 削除済みのため undefined

2)seal:追加と削除の両方を防ぐ

拡張禁止(preventExtensions)と同様に新規プロパティの追加はできませんが、さらに既存のプロパティやメソッドの削除も不可能になります。ただし、既存プロパティの値の変更は引き続き可能です。このタスクには Object.seal() メソッドを使用します。

サンプルコード

<html>
<body>
<script>
    var object1 = {
       prop1: 1
    };
    Object.seal(object1);
    object1.prop1 = 2;             // 既存プロパティの値は変更できる
    delete object1.prop1;          // ただし削除はできない
    try {
       Object.defineProperty(object1, 'prop2', {
       value: 2
    });
    } catch (err) {
       document.write(err);
    }
    document.write("</br>");
    document.write(object1.prop1); // sealにより削除は不可だが更新は可能 → 2
</script>
</body>
</html>

実行結果

TypeError: Cannot define property prop2, object is not extensible
2 // sealにより削除はできないが、値の更新は可能

3)freeze:オブジェクトを完全に固定する

seal の機能に加えて、既存プロパティの値の変更まで禁止します。つまり、プロパティの追加・削除・変更のすべてが不可能になり、オブジェクトをイミュータブル(不変)な状態にできます(読み取り自体は可能です)。オブジェクトの凍結には Object.freeze() メソッドを使用します。

サンプルコード

<html>
<body>
<script>
    var object1 = {
       prop1: 1
    };
    Object.freeze(object1);
    object1.prop1 = 2;             // 値の変更は無視される
    delete object1.prop1;          // 削除もできない
    try {
       Object.defineProperty(object1, 'prop2', {
       value: 2
    });
    } catch (err) {
       document.write(err);
    }
    document.write("</br>");
    document.write(object1.prop1); // 2に更新しても出力は1のまま
</script>
</body>
</html>

実行結果

TypeError: Cannot define property prop2, object is not extensible
1 // freezeにより削除も更新も不可

補足:状態の確認メソッドとstrictモードでの挙動

  • Object.isExtensible():オブジェクトが拡張可能かどうかを判定
  • Object.isSealed():オブジェクトが封印されているかどうかを判定
  • Object.isFrozen():オブジェクトが凍結されているかどうかを判定

上記の例のように非ストリクトモードでは、規約に反する操作はエラーなく静かに失敗しますが、"use strict" を宣言したストリクトモードでは TypeError がスローされる点に注意してください。

また、freeze による凍結は浅い(shallow)凍結です。ネストされた子オブジェクトのプロパティまでは凍結されないため、オブジェクト全体を完全に不変にしたい場合は、各階層に対して再帰的に freeze を適用する必要があります。


  1. JavaScriptでインポートしたオブジェクトを分割代入(デストラクチャリング)する方法

    JavaScriptでは、ESモジュールからインポートしたオブジェクトに対して分割代入(デストラクチャリング)を使うことで、必要なプロパティだけを個別の変数として簡潔に取り出すことができます。ここでは、import で読み込んだオブジェクトを分割代入する具体的な手順とコード例を紹介します。 ポイント:分割代入の基本構文 オブジェクトの分割代入は、次のように波括弧 { } の中に取り出したいプロパティ名を並べて記述します。let {プロパティ1, プロパティ2, プロパティ3} = オブジェクト;この構文は、インポートされたデフォルトエクスポートのオブジェクトにもそのまま適用できます。 コード例

  2. JavaScriptで多次元オブジェクトを作成する方法【サンプルコード付き】

    はじめに JavaScriptでは、オブジェクトのプロパティの値として別のオブジェクトを持たせることで、多次元(ネストされた)オブジェクトを作成できます。この構造を活用すると、氏名や学校情報、住所のように階層関係のあるデータを、直感的かつ整理された形で表現することが可能です。 サンプルコード 以下は、多次元JavaScriptオブジェクトを作成し、コンソールに表示するためのコード例です。 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /