有没有办法让Object.freeze()成为一个JavaScript日期? [英] Is there a way to Object.freeze() a JavaScript Date?
问题描述
Object.freeze()
方法冻结一个对象:即阻止向其添加新属性;防止删除现有属性;并防止现有属性或其可枚举性,可配置性或可写性被更改。实质上,该对象实际上是不可变的。该方法返回被冻结的对象。
The
Object.freeze()
method freezes an object: that is, prevents new properties from being added to it; prevents existing properties from being removed; and prevents existing properties, or their enumerability, configurability, or writability, from being changed. In essence the object is made effectively immutable. The method returns the object being frozen.
我原以为在某个日期调用冻结会阻止对该日期的更改,但它会似乎不起作用。这是我正在做的事情(运行Node.js v5.3.0):
I was expecting that calling freeze on a date would prevent changes to that date, but it does not appear to be working. Here's what I am doing (running 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
的调用要么失败要么什么都不做。任何想法如何冻结日期?
I would have expected the call to setTime
to either fail or do nothing. Any ideas how to freeze a date?
推荐答案
有没有办法去Object.freeze()一个JavaScript日期?
Is there a way to Object.freeze() a JavaScript Date?
我不这么认为。您可以关闭,但请参阅下面的行。但首先让我们看看为什么 Object.freeze
不起作用。
I don't think so. You can get close, though, see under the line below. But first let's see why just Object.freeze
doesn't work.
I期待在某个日期冻结呼叫会阻止对该日期的更改...
I was expecting that calling freeze on a date would prevent changes to that date...
如果 日期
使用对象属性来保存其内部时间值,但事实并非如此。它使用 [ [DateValue]]
内部广告位 。 内部插槽不是属性:
It would if Date
used an object property to hold its internal time value, but it doesn't. It uses a [[DateValue]]
internal slot instead. Internal slots aren't properties:
内部插槽对应于与对象关联并由各种ECMAScript规范算法使用的内部状态。内部插槽不是对象属性...
Internal slots correspond to internal state that is associated with objects and used by various ECMAScript specification algorithms. Internal slots are not object properties...
因此冻结对象对其变异<$的能力没有任何影响c $ c> [[DateValue]] 内部广告位。
So freezing the object doesn't have any effect on its ability to mutate its [[DateValue]]
internal slot.
你可以冻结日期
,或者无论如何都有效:用无操作函数(或抛出错误的函数)替换所有mutator方法然后冻结
它。但是,通过观察 zzzzBov (很好!),这不会阻止某人做 Date.prototype.setTime.call(d,0)
(故意尝试绕过冻结的对象,或作为他们正在使用的一些复杂代码的副产品)。所以它是关闭,但没有雪茄。
You can freeze a Date
, or effectively so anyway: Replace all its mutator methods with no-op functions (or functions that throw an error) and then freeze
it. But as observed by zzzzBov (nice one!), that doesn't prevent someone from doing Date.prototype.setTime.call(d, 0)
(in a deliberate attempt to get around the frozen object, or as a byproduct of some complicated code they're using). So it's close, but no cigar.
这是一个例子(我在这里使用ES2015功能,因为我看到在你的代码中让
,所以你需要一个最近的浏览器来运行它;但这也可以用ES5专用功能完成):
Here's an example (I'm using ES2015 features here, since I saw that let
in your code, so you'll need a recent browser to run it; but this can be done with ES5-only features as well):
"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
的所有mutator方法都以 set
开头,但如果没有,那么很容易调整以上内容。
I think all the mutator methods of Date
start with set
, but if not it's easy to tweak the above.
这篇关于有没有办法让Object.freeze()成为一个JavaScript日期?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!