有没有办法让Object.freeze()成为一个JavaScript日期? [英] Is there a way to Object.freeze() a JavaScript Date?

查看:106
本文介绍了有没有办法让Object.freeze()成为一个JavaScript日期?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据 MDN Object.freeze()文档


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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆