这是一个非常好的问题!
TJ Crowder的答案有一个很好的解决方案,但它让我思考:我们还能做什么?我们该如何解决Date.prototype.setTime.call(yourFrozenDate)
?
第一次尝试:“包装器”
一种直接的方法是提供一个AndrewDate
包装日期的函数。它具有日期减去设置者的所有内容:
function AndrewDate(realDate) {
var proto = Date.prototype;
var propNames = Object.getOwnPropertyNames(proto)
.filter(propName => !propName.startsWith('set'));
return propNames.reduce((ret, propName) => {
ret[propName] = proto[propName].bind(realDate);
return ret;
}, {});
}
var date = AndrewDate(new Date());
date.setMonth(2);
这是创建一个具有实际日期对象具有的所有属性并用于Function.prototype.bind
设置其属性的对象this
。
这不是一个愚蠢的方法来收集密钥,但是希望您能看到我的意图。
但是,等等...再四处看看,我们可以看到有更好的方法可以做到这一点。
第二次尝试:代理
function SuperAndrewDate(realDate) {
return new Proxy(realDate, {
get(target, prop) {
if (!prop.startsWith('set')) {
return Reflect.get(target, prop);
}
}
});
}
var proxyDate = SuperAndrewDate(new Date());
我们解决了!
...有点。可以看到,Firefox是目前唯一实现代理的,出于某些奇怪的原因,无法代理日期对象。此外,您会注意到您仍然可以做类似的事情,'setDate' in proxyDate
并且您会在控制台中看到完成情况。为了克服这一点,需要提供更多的陷阱;具体而言,has
,enumerate
,ownKeys
,getOwnPropertyDescriptor
,谁知道是什么奇怪的边缘情况下,有!
...因此,再三考虑,这个答案几乎没有意义。但是至少我们玩得开心,对吗?
Object.freeze()
整个对象。似乎可行,除了这个小小的日期问题。