Jak obejść zmienność w pliku moment.js?

107

Napotkałem problem polegający na tym, że muszę przechowywać wartości początkowe obiektu chwili, ale mam pewne problemy z zapobieganiem zmianie mojej zmiennej wraz z oryginalnym obiektem.

Niestety Object.freeze () nie działa, ponieważ moment.js zwraca błąd „Nieprawidłowa data”, gdy próbuję to sformatować.

Shengbo1618
źródło
3
A kod wygląda tak…? Jeśli chcesz zapisać wartość początkową, zapisz wartość czasu, dostępną za pomocą metody valueOf lub niejawnej konwersji na liczbę.
RobG
kiedy twoja zmienna jest ustawiona, jest ustawiona, nie zmieni się automagicznie, więc raczej staraj się nie ustawiać jej raz po raz
john Smith

Odpowiedzi:

185

W NPM jest wtyczka Moment.js o nazwie frozen-moment - możesz użyć moment().freeze()zamiast Object.freeze(moment()).

W przeciwnym razie vanilla Moment.js ma clonemetodę, która powinna pomóc ci uniknąć problemów ze zmiennością, więc możesz zrobić coś takiego:

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

AKTUALIZACJA:

Minęły dwa lata, odkąd napisałem tę odpowiedź. W tym czasie pojawiła się kolejna biblioteka do pracy z datami i zyskała dużą popularność: https://date-fns.org/

Ta biblioteka jest domyślnie niezmienna i jest zgodna z modułową, funkcjonalną architekturą, co oznacza, że ​​lepiej nadaje się do wstrząsania drzewem i tworzenia pakietów po stronie klienta. Jeśli pracujesz nad projektem, który w znacznym stopniu wykorzystuje Webpack po stronie klienta i zauważysz, że Moment.js sprawia problemy z twoją kompilacją, a nawet jeśli zmienność Moment.js powoduje wiele bólu głowy, to powinien date-fnsspróbować.

brzytwa
źródło
Cóż, używam momentu.js we wtyczce fullCalendar i okazuje się, że otrzymywałem dane obiektu momentu z późniejszego stanu mojego zdarzenia niż powinienem. Problemy ze zmiennością są jednak zdecydowanie problemem w przypadku moment.js, więc bardzo dziękuję za sugestię i przepraszam, że zmarnowałem Twój czas.
Shengbo1618
24
Możesz manipulować zapisaną momentzmienną bez jej mutowania: po prostu użyj clone () w ten sposób:zz = moment(); zz.clone().add(3, 'h').toISOString();
Quake1TF
5
Zauważ, że date-fns ma bardzo słabą obsługę stref czasowych i nie obsługuje dat UTC.
mjuopperi
3
Używam go już date-fnsod jakiegoś czasu, ale od tego czasu musiałem wskoczyć do starszego kodu za pomocą Moment and boy, czy ten post uratował mnie przed wyskoczeniem z okna.
Yuschick
dayjsjest również dobrą alternatywą, ponieważ ma interfejsy API podobne do Moment.js z niezmiennym charakterem. (Od marca 2019 roku brakuje obsługi stref czasowych, ale jest to dość nowa biblioteka i widzę, że prace trwają.)
Tomoyuki Aota
2

To stare pytanie i przeprosiny za bezwstydną autopromocję, ponieważ nie jest to moim zamiarem, mam tylko nadzieję, że komuś pomoże.

Oprócz tego, co mówi razorbeard ( .clone()itp.), Stworzyłem moduł NPM, który dołącza niezmienne metody do wszystkiego, co Moment.js jest dostarczane po wyjęciu z pudełka. Celem nie jest przerywanie istniejącego kodu, więc moduł dodaje nowe metody z Immudopiskiem do jego nazwy.

Każda instancja zwrócona przez chwilę fabryka będzie udekorowana niezmiennymi metodami, np. moment().startOf()Będzie miała odpowiednie startOfImmu(), add()będzie miała addImmu()itd. Każda z nich zwraca nowy moment zamiast modyfikować istniejący. Aby z niego skorzystać, wystarczy przejść przez momentfabrykę, momentImmutableMethodsaby uzyskać dostęp do nowych niezmiennych metod. Przykład:

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"

Jest na NPM pod adresem https://www.npmjs.com/package/moment-immutable-methods

spirytus
źródło