Wie kann ich die Veränderbarkeit in moment.js umgehen?

105

Ich bin auf ein Problem gestoßen, bei dem ich die Anfangswerte eines Momentobjekts speichern muss, aber ich habe Probleme, zu verhindern, dass sich meine Variable zusammen mit dem ursprünglichen Objekt ändert.

Leider funktioniert Object.freeze () nicht, da moment.js einen Fehler "Ungültiges Datum" zurückgibt, wenn ich versuche, dies zu formatieren.

Shengbo1618
quelle
3
Und der Code sieht aus wie ...? Wenn Sie den Anfangswert speichern möchten, speichern Sie den Zeitwert, der mit der valueOf- Methode oder der impliziten Konvertierung in eine Zahl verfügbar ist .
RobG
Sobald Ihre Variable gesetzt ist, wird sie gesetzt, sie ändert sich nicht automatisch, also versuchen Sie lieber, sie nicht immer wieder zu setzen
John Smith

Antworten:

182

Es gibt ein Moment.js-Plugin auf NPM namens Frozen-Moment - Sie können es moment().freeze()anstelle von verwenden Object.freeze(moment()).

Andernfalls verfügt vanilla Moment.js über eine cloneMethode, mit der Sie Veränderbarkeitsprobleme vermeiden können. Sie können also Folgendes tun:

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

AKTUALISIEREN:

Es ist zwei Jahre her, seit ich diese Antwort geschrieben habe. In dieser Zeit ist eine andere Bibliothek für die Arbeit mit Datumsangaben aufgetaucht und hat viel Anklang gefunden: https://date-fns.org/

Diese Bibliothek ist standardmäßig unveränderlich und folgt einer modularen, funktionalen Architektur, was bedeutet, dass sie besser für das Schütteln von Bäumen und das clientseitige Bündeln geeignet ist. Wenn Sie an einem Projekt arbeiten, das Webpack auf der Clientseite in großem Umfang nutzt, und feststellen, dass Moment.js Probleme mit Ihrem Build verursacht, oder wenn die Veränderlichkeit von Moment.js Ihnen große Kopfschmerzen bereitet, dann haben Sie Probleme sollte es date-fnsversuchen.

Rasiermesser
quelle
Nun, ich verwende moment.js im fullCalendar-Plugin und es stellte sich heraus, dass ich die Moment-Objektdaten aus einem späteren Status meines Ereignisses erhalten habe, als ich eigentlich sollte. Mutabilitätsprobleme sind definitiv eine Sache mit moment.js, also vielen Dank für den Vorschlag und entschuldigen Sie, dass ich Ihre Zeit verschwendet habe.
Shengbo1618
24
Sie können gespeicherte momentVariablen manipulieren , ohne sie zu mutieren: Verwenden Sie einfach clone () wie zz = moment(); zz.clone().add(3, 'h').toISOString();
folgt
5
Beachten Sie, dass date-fns eine sehr schlechte Zeitzonenunterstützung und keine Unterstützung für UTC-Daten hat.
Mjuopperi
3
Ich benutze es date-fnsjetzt schon eine Weile, musste aber seitdem mit Moment und Boy in alten Code springen. Hat mich dieser Beitrag davor bewahrt, aus einem Fenster zu springen?
Yuschick
dayjsist auch eine gute Alternative, da es APIs ähnlich wie Moment.js mit unveränderlicher Natur hat. (Ab März 2019 fehlt die Zeitzonenunterstützung, aber dies ist eine ziemlich neue Bibliothek, und ich kann beobachten, dass die Arbeit noch nicht abgeschlossen ist.)
Tomoyuki Aota
2

Es ist eine alte Frage und Entschuldigung für schamlose Eigenwerbung, da dies nicht meine Absicht ist, hoffe nur, dass es jemandem hilft.

Zusätzlich zu dem, was razorbeard sagt ( .clone()usw.), habe ich ein NPM-Modul erstellt, das unveränderliche Methoden an alle Moment.js anfügt, die standardmäßig mitgeliefert werden. Der vorhandene Code soll nicht beschädigt werden, daher fügt das Modul neue Methoden hinzu, Immudie an seinen Namen angehängt werden.

Jede Instanz, die von der Momentfabrik zurückgegeben wird, wird mit unveränderlichen Methoden dekoriert, z. B. moment().startOf()hat entsprechende startOfImmu(), add()hat addImmu()usw. Jede dieser Instanzen gibt einen neuen Moment zurück, anstatt den vorhandenen zu ändern. Um es zu verwenden, übergeben Sie einfach die momentFactory momentImmutableMethods, um Zugriff auf neue unveränderliche Methoden zu erhalten. Beispiel:

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"

Es ist auf NPM unter https://www.npmjs.com/package/moment-immutable-methods

Spirytus
quelle