1. ホーム
  2. javascript

JavaScriptのDateをObject.freeze()する方法はありますか?

2023-08-24 07:48:23

質問

によると MDN Object.freeze() ドキュメント :

Object.freeze() メソッドはオブジェクトをフリーズさせます。 つまり、新しいプロパティが追加されるのを防ぎ、既存のプロパティが削除されるのを防ぎ、既存のプロパティ、またはその列挙性、設定性、書き込み性が変更されるのを防ぎます。要するに、オブジェクトは事実上不変となるのです。このメソッドは、凍結されたオブジェクトを返します。

私は、ある日付でfreezeを呼び出すとその日付の変更を防ぐことができると期待していましたが、それは動作していないようです。 以下は、私が行っていることです (Node.js v5.3.0 を実行しています)。

let d = new Date()
Object.freeze(d)
d.setTime(0)
console.log(d) // Wed Dec 31 1969 16:00:00 GMT-0800 (PST)

への呼び出しを期待したのですが setTime への呼び出しが失敗するか、何もしないことを期待します。日付を凍結する方法について何かアイデアがありますか?

どのように解決するのですか?

<ブロッククオート

JavaScriptのDateをObject.freeze()する方法はありますか?

ないと思います。あなたが得ることができる 閉じる を得ることができますが、下の行の下を参照してください。しかし、その前に、なぜ単に Object.freeze がうまくいかない理由を見てみましょう。

ある日付でfreezeを呼び出すと、その日付の変更ができなくなると思っていたのですが...。

それは もし Date は内部の時間値を保持するためにオブジェクトプロパティを使用していましたが、そうではありません。それは [[DateValue]] 内部スロット の代わりに 内部スロット はプロパティではありません。

内部スロットは、オブジェクトに関連付けられ、様々なECMAScriptの仕様アルゴリズムによって使用される内部状態に対応します。内部スロットはオブジェクトのプロパティではありません...

つまり、オブジェクトをフリーズさせても、そのオブジェクトの [[DateValue]] 内部スロットを変異させる能力に影響を与えません。


あなたは できます を凍結することができます。 Date をフリーズさせることができます。あるいは、とにかく効果的にそうすることができます。そのすべてのミューテータ・メソッドをno-op関数(またはエラーを投げる関数)に置き換えて、次に freeze とすることができます。しかし が観測した によって zzzzBov (いいね!) を行うことを妨げるものではありません。 Date.prototype.setTime.call(d, 0) (凍結したオブジェクトを回避するための意図的な試み、または使用している複雑なコードの副産物として) を行うことを妨げるものではありません。つまり、それは 閉じる ですが、葉巻はありません。

以下はその例です(ここではES2015の機能を使用しています、私が見たのは let を見たので、これを実行するには最近のブラウザが必要です。しかし、これは ES5 のみの機能でも実行できます)。

"use strict";

let d = new Date();
freezeDate(d);
d.setTime(0);
snippet.log(d);

function nop() {
}

function freezeDate(d) {
  allNames(d).forEach(name => {
    if (name.startsWith("set") && typeof d[name] === "function") {
      d[name] = nop;
    }
  });
  Object.freeze(d);
  return d;
}
function allNames(obj) {
  var names = Object.create(null); // Or use Map here
  var thisObj;
  
  for (thisObj = obj; thisObj; thisObj = Object.getPrototypeOf(thisObj)) {
    Object.getOwnPropertyNames(thisObj).forEach(name => {
      names[name] = 1;
    });
  }
  return Object.keys(names);
}
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

I を考える のすべてのミューテーターメソッドは Date で始まる set でなければ、上記を微調整するのは簡単です。