Як мені подолати мутабельність у moment.js?


106

Я зіткнувся з проблемою, коли мені потрібно зберігати початкові значення об'єкта моменту, але у мене виникають певні проблеми, щоб запобігти зміні моєї змінної разом з оригінальним об'єктом.

На жаль, Object.freeze () не працює, оскільки moment.js повертає помилку "Недійсна дата", коли я намагаюся це відформатувати.


3
А код виглядає як…? Якщо ви хочете зберегти початкове значення, збережіть значення часу, доступне за допомогою методу valueOf або неявного перетворення в число.
RobG

як тільки ваша змінна буде встановлена, вона буде встановлена, вона не буде автоматично змінюватися автоматично, тому краще дивіться, щоб не встановлювати її знову і знову
Джон Сміт,

Відповіді:


184

На NPM є плагін Moment.js під назвою заморожений момент - його можна використовувати moment().freeze()замість Object.freeze(moment()).

В іншому випадку, ванільний Moment.js має cloneметод, який повинен допомогти вам уникнути проблем із змінними можливостями , щоб ви могли зробити щось подібне:

var a = moment(),
    b = a.clone(); // or moment(a)

ОНОВЛЕННЯ:

Минуло два роки, як я написав цю відповідь. У цей час вийшла ще одна бібліотека для роботи з датами і отримала багато тяги: https://date-fns.org/

Ця бібліотека є незмінною за замовчуванням і відповідає модульній, функціональній архітектурі, а це означає, що вона краще підходить для струшування дерев та зшивання на стороні клієнта. Якщо ви працюєте над проектом, який широко використовує Webpack на стороні клієнта, і виявите, що Moment.js доставляє вам проблеми з вашою збіркою, або навіть якщо незмінність Moment.js заподіює вам багато головного болю, то ви слід date-fnsспробувати.


Ну, я використовую moment.js у плагіні fullCalendar, і виявляється, я отримував дані про об'єкт моменту з пізнішого стану моєї події, ніж я повинен був. Проблеми з переміщенням, безумовно, є справою з moment.js, тому дуже дякую за пропозицію і вибачте, що ви витратили ваш час.
Shengbo1618

24
Ви можете керувати збереженою momentзмінною, не змінюючи її: просто використовуйте clone () так:zz = moment(); zz.clone().add(3, 'h').toISOString();
Quake1TF

5
Зауважте, що дата-fns має дуже погану підтримку часового поясу і не підтримує дати UTC.
mjuopperi

3
Я використовую date-fnsдеякий час зараз, але з тих пір довелося перейти до застарілого коду за допомогою Моменту та хлопчика, чи врятував мене цей пост від вистрибування у вікно.
Ющик

dayjsтакож є хорошою альтернативою, оскільки він має API, подібний до Moment.js з незмінним характером. (Станом на березень 2019 року йому не вистачає підтримки часового поясу, але це досить нова бібліотека, і я можу спостерігати, що робота триває.)
Томоюкі Аота,

2

Це старе питання та вибачення за безсоромне саморекламування, оскільки це не мій намір, просто сподіваюся, що це комусь допоможе.

На додаток до того, що говорить бритва ( .clone()тощо), я створив модуль NPM, який приєднує незмінні методи до того, що Moment.js виходить із коробки. Намір не порушувати існуючий код, тому модуль додає нові методи із додаванням Immuдо його імені.

Кожен екземпляр, що повертається моментом, фабрика буде прикрашена незмінними методами, наприклад moment().startOf(), матиме відповідні startOfImmu(), add()матиме і addImmu()т. Д. Кожен з цих повертає новий момент, а не змінює існуючий. Для його використання просто пройдіть momentзавод, momentImmutableMethodsщоб отримати доступ до нових незмінних методів. Приклад:

var moment = require('moment'); // or moment-timezone 
import { momentImmutableMethods } from 'moment-immutable-methods';

// to decorate instances with immutable methods we need to extend moment factory as below:
momentImmutableMethods(moment);

// now every instance returned by moment will have Immu methods attached.


// IMMUTABLE EXAMPLE
// we using immutable methods that were attached to every instance, these have Immu appended to original name
const ddd = moment({
  hour: 5,
  minute: 10
});
// Moment {_isAMomentObject: true, _i: {…}, _isUTC: false, _pf: {…}, _locale: Locale, …}
const eee = ddd.startOfImmu('day');
// Moment {_isAMomentObject: true, _i: {…}, _isUTC: false, _pf: {…}, _locale: Locale, …}
console.log(ddd === eee);
// false
const fff = eee.startOfImmu('month');
// Moment {_isAMomentObject: true, _i: {…}, _isUTC: false, _pf: {…}, _locale: Locale, …}
console.log(ddd === fff);
// false
console.log(eee === fff);
// false
console.log(ddd.format('DD/MM/YY HH:mma'));
// "14/04/18 05:10am"
console.log(eee.format('DD/MM/YY HH:mma'));
// "14/04/18 00:00am"
console.log(fff.format('DD/MM/YY HH:mma'));
// "08/04/18 00:00am"

Її про NPM за адресою https://www.npmjs.com/package/moment-immutable-methods

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.