Це справді гарне запитання!
Відповідь 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()весь об’єкт. Здається, це працює, за винятком цієї непомітної проблеми з датою.