Как обойти изменчивость в moment.js?

107

Я столкнулся с проблемой, когда мне нужно сохранить начальные значения объекта момента, но у меня возникли проблемы с предотвращением изменения моей переменной вместе с исходным объектом.

К сожалению, Object.freeze () не работает, потому что moment.js возвращает ошибку «Недопустимая дата», когда я пытаюсь ее отформатировать.

Шэнбо1618
источник
3
А код выглядит как…? Если вы хотите сохранить начальное значение, сохраните значение времени, доступное с помощью метода valueOf или неявного преобразования в число.
RobG
как только ваша переменная установлена, она установлена, она не будет меняться автоматически, так что лучше постарайтесь не устанавливать ее снова и снова
Джон Смит

Ответы:

185

В NPM есть плагин Moment.js под названием frozen-moment - вы можете использовать moment().freeze()вместо Object.freeze(moment()).

В противном случае в vanilla 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
Обратите внимание, что date-fns имеет очень плохую поддержку часовых поясов и не поддерживает даты в формате UTC.
mjuopperi
3
Я уже date-fnsнекоторое время использую, но с тех пор мне пришлось перейти на устаревший код, используя Moment, и мальчик, этот пост спас меня от выпрыгивания из окна.
Ющик
dayjsтакже является хорошей альтернативой, поскольку у него есть API-интерфейсы, подобные Moment.js, с неизменной природой. (По состоянию на март 2019 года в нем отсутствует поддержка часовых поясов, но это довольно новая библиотека, и я могу наблюдать, что работа продолжается.)
Томоюки Аота
2

Это старый вопрос, и извинения за бесстыдную саморекламу, поскольку это не мое намерение, просто надеюсь, что это кому-то поможет.

В дополнение к тому, что говорит razorbeard (и .clone()т. Д.), Я создал модуль NPM, который присоединяет неизменяемые методы ко всему, что Moment.js поставляется из коробки. Цель состоит в том, чтобы не нарушать существующий код, поэтому модуль добавляет новые методы с Immuдобавлением к его имени.

Каждый экземпляр, возвращаемый фабрикой моментов, будет украшен неизменяемыми методами, например, moment().startOf()будет иметь соответствующие startOfImmu(), add()будут иметь addImmu()и т. Д. Каждый из них возвращает новый момент, а не изменяет существующий. Чтобы использовать его, просто передайте momentfactory, 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

Spirytus
источник