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