0

I have the following JavaScript (Typescript) sample, where I initialise an Array and then push a timestamp of every hour until the end timestamp is included in the range.

let res = [start];
while (res[res.length - 1].isBefore(end)) {
    let nextTime = res[res.length - 1].add(1, 'hour'); // add one hour to the previous result - this is a moment.js instance
    console.log('loop', nextTime.format())
    res.push(nextTime);
}
res.forEach(val => console.log('result', val.format()))

The console.log from the loop logs out the expected values e.g.

loop 2017-03-27T18:00:00+01:00

loop 2017-03-27T19:00:00+01:00

loop 2017-03-27T20:00:00+01:00

However, the resulting array only seems to contain the correct number of records but they are all the final value, e.g.

result 2017-03-28T18:00:00+01:00

result 2017-03-28T18:00:00+01:00

Why is this?

2
  • What's nextTime, a MomentJS instance? Commented Mar 28, 2017 at 16:15
  • @T.J.Crowder yes, have updated the question Commented Mar 28, 2017 at 16:15

1 Answer 1

5

MomentJS objects are mutable (changeable) objects with state. Calling add on a MomentJS object modifies it, but doesn't create a new object; it just returns a reference to the same object. So say you start with this:

     +−−−−−−−−−+        
res−>| (array) |        
     +−−−−−−−−−+        +−−−−−−−−−−+    
     | 0       |−−−−−−−>| (object) |    
     +−−−−−−−−−+        +−−−−−−−−−−+   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ 
                        | d:       |−−>|                  (Date)                  | 
                        +−−−−−−−−−−+   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ 
                                       | [[TimeValue]]: 2017−03−27T18:00:00+01:00 |
                                       +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+

Your

let nextTime = moment(res[res.length - 1]).add(1, 'hour');
// ...
res.push(nextTime);

modifies that object and pushes another reference to it onto res:

     +−−−−−−−−−+        
res−>| (array) |        
     +−−−−−−−−−+        +−−−−−−−−−−+   
     | 0       |−−−−+−−>| (object) |   
     | 1       |−−−/    +−−−−−−−−−−+   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
     +−−−−−−−−−+        | d:       |−−>|                  (Date)                  |
                        +−−−−−−−−−−+   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
                                       | [[TimeValue]]: 2017−03−27T19:00:00+01:00 |
                                       +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+

Notice how the state of the object (the [[TimeValue]] in the Date used by the MomentJS object) has changed.

If you do it again, we just update it again:

     +−−−−−−−−−+        
res−>| (array) |        
     +−−−−−−−−−+        +−−−−−−−−−−+   
     | 0       |−−−−+−−>| (object) |   
     | 1       |−−−/    +−−−−−−−−−−+   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
     | 2       |−−/     | d:       |−−>|                  (Date)                  |
     +−−−−−−−−−+        +−−−−−−−−−−+   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
                                       | [[TimeValue]]: 2017−03−27T20:00:00+01:00 |
                                       +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+

Instead, you want to create a new object. You can do that by cloning the original with moment.

let nextTime = moment(res[res.length - 1]).add(1, 'hour');
// ------------^^^^^^^   ----------------^
// ...
res.push(nextTime);

If you do that, then from the same starting point, we get:

     +−−−−−−−−−+        
res−>| (array) |        
     +−−−−−−−−−+        +−−−−−−−−−−+   
     | 0       |−−−−−−−>| (object) |   
     | 1       |−−−−+   +−−−−−−−−−−+   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
     | 2       |−−+ |   | d:       |−−>|                  (Date)                  |
     +−−−−−−−−−+  | |   +−−−−−−−−−−+   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ 
                  | |                  | [[TimeValue]]: 2017−03−27T18:00:00+01:00 | 
                  | |   +−−−−−−−−−−+   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ 
                  | +−−>| (object) |                                                
                  |     +−−−−−−−−−−+   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ 
                  |     | d:       |−−>|                  (Date)                  |
                  |     +−−−−−−−−−−+   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ 
                  +−−−−>               | [[TimeValue]]: 2017−03−27T19:00:00+01:00 | 
                        +−−−−−−−−−−+   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ 
                        | (object) |                                                
                        +−−−−−−−−−−+   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ 
                        | d:       |−−>|                  (Date)                  |
                        +−−−−−−−−−−+   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
                                       | [[TimeValue]]: 2017−03−27T20:00:00+01:00 |
                                       +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
Sign up to request clarification or add additional context in comments.

1 Comment

@ArthurCinader can guess the library which OP are using is not too easy, and solve the problem so quickly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.