如何解决moment.js中的可变性?


106

我遇到了一个问题,我必须存储一下矩对象的初始值,但是在阻止变量随原始对象变化时遇到了一些麻烦。

不幸的是,Object.freeze()无法正常工作,因为当我尝试格式化时,moment.js返回“ Invalid date”错误。


3
代码看起来像……?如果要存储初始值,请存储时间值,可以使用valueOf方法或隐式转换为number来获取时间值。
RobG

一旦设置了变量,它就会被设置,它不会自动改变,所以宁愿不要一次又一次地设置它
约翰·史密斯

Answers:


184

NPM上有一个名为Frozen -moment的Moment.js插件-您可以使用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尝试一下。


好吧,我在fullCalendar插件中使用了moment.js,事实证明,我从事件的后一个状态获取了瞬间对象数据,而这比我想象的要晚。可变性问题绝对是moment.js的问题,因此非常感谢您的建议,对不起,我浪费了您的时间。
Shengbo1618

24
您可以操作存储的moment变量而无需对其进行zz = moment(); zz.clone().add(3, 'h').toISOString();
更改

5
请注意,date-fns的时区支持非常差,并且不支持UTC日期。
mjuopperi

3
我已经使用date-fns了一段时间,但此后不得不使用Moment和boy跳入旧代码,这篇文章使我免于跳出窗口。
Yuschick

dayjs也是一种不错的选择,因为它具有类似于Moment.js的具有不变性质的API。(截至2019年3月,它没有时区支持,但这是一个相当新的库,我可以观察到工作正在进行中。)
Tomoyuki Aota

2

这是一个老问题,对无耻自我提升表示歉意,因为这不是我的意图,只是希望它能对某人有所帮助。

除了razorbeard所说的(.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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.