Làm cách nào để giải quyết khả năng thay đổi trong moment.js?


106

Tôi đã gặp sự cố trong đó tôi phải lưu trữ các giá trị ban đầu của một đối tượng thời điểm nhưng tôi đang gặp một số khó khăn khi ngăn biến của mình thay đổi cùng với đối tượng gốc.

Rất tiếc, Object.freeze () không hoạt động, vì moment.js trả về lỗi "Ngày không hợp lệ" khi tôi cố định dạng.


3
Và mã trông giống như…? Nếu bạn muốn lưu trữ giá trị ban đầu, hãy lưu trữ giá trị thời gian, có sẵn bằng cách sử dụng phương thức valueOf hoặc chuyển đổi ngầm định thành số.
RobG

một lần biến của bạn được thiết lập, nó được thiết lập, nó sẽ không thay đổi automagically, vì vậy thay vì nhìn vào không đặt nó một lần nữa và một lần nữa
john Smith

Câu trả lời:


184

Có một plugin Moment.js trên NPM được gọi là thời điểm bị đóng băng - Bạn có thể sử dụng moment().freeze()thay thế Object.freeze(moment()).

Mặt khác, vanilla Moment.js có một clonephương pháp giúp bạn tránh các vấn đề về khả năng thay đổi, vì vậy bạn có thể làm điều gì đó như sau:

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

CẬP NHẬT:

Đã hai năm kể từ khi tôi viết câu trả lời này. Trong thời gian này, một thư viện khác để làm việc với ngày tháng đã xuất hiện và thu được rất nhiều sức hút: https://date-fns.org/

Thư viện này là bất biến theo mặc định và tuân theo kiến ​​trúc mô-đun, chức năng, có nghĩa là nó phù hợp hơn với rung cây và gói phía máy khách. Nếu bạn đang thực hiện một dự án sử dụng rộng rãi Webpack ở phía máy khách và nhận thấy rằng Moment.js đang khiến bạn gặp rắc rối với bản dựng của mình hoặc thậm chí nếu khả năng thay đổi của Moment.js đang khiến bạn rất đau đầu, thì bạn nên date-fnsthử.


Chà, tôi đang sử dụng moment.js trong plugin fullCalendar và hóa ra là tôi đang nhận dữ liệu đối tượng thời điểm từ trạng thái sau sự kiện của mình so với dự kiến. Tuy nhiên, các vấn đề về khả năng thay đổi chắc chắn là một vấn đề với moment.js, vì vậy, cảm ơn bạn rất nhiều vì đề xuất và xin lỗi vì tôi đã lãng phí thời gian của bạn.
Shengbo1618

24
Bạn có thể thao tác với momentbiến được lưu trữ mà không làm thay đổi nó: chỉ cần sử dụng clone () như thế này:zz = moment(); zz.clone().add(3, 'h').toISOString();
Quake1TF

5
Lưu ý rằng date-fns có hỗ trợ múi giờ rất kém và không hỗ trợ ngày UTC.
mjuopperi

3
Tôi đã sử dụng được date-fnsmột thời gian nhưng kể từ đó phải nhảy vào mã kế thừa bằng cách sử dụng Moment và cậu bé, bài đăng này đã giúp tôi thoát khỏi việc nhảy ra khỏi cửa sổ.
Yuschick

dayjscũng là một giải pháp thay thế tốt vì nó có các API tương tự như Moment.js với bản chất bất biến. (Kể từ tháng 3 năm 2019, nó thiếu hỗ trợ múi giờ nhưng đây là một thư viện khá mới và tôi có thể quan sát thấy công việc đang diễn ra.)
Tomoyuki Aota

2

Đó là một câu hỏi cũ và lời xin lỗi vì đây không phải là ý định của tôi, chỉ hy vọng nó sẽ giúp ích cho ai đó.

Ngoài những gì razorbeard nói (.clone() v.v.), tôi đã tạo mô-đun NPM gắn các phương thức bất biến vào bất kỳ thứ gì Moment.js đi kèm. Mục đích không phải là phá vỡ mã hiện tại để mô-đun thêm các phương thức mới với Immutên của nó.

Mỗi trường hợp được trả về bởi nhà máy thời điểm sẽ được trang trí bằng các phương thức bất biến, ví dụ: moment().startOf()sẽ có tương ứng startOfImmu(), add()sẽ có, addImmu()v.v. Mỗi trường hợp đó trả về khoảnh khắc mới thay vì sửa đổi khoảnh khắc hiện có. Để sử dụng nó, chỉ cần vượt qua momentnhà máy momentImmutableMethodsđể có quyền truy cập vào các phương thức bất biến mới. Thí dụ:

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"

Nó có trên NPM tại https://www.npmjs.com/package/moment-immutable-methods

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.