Recently, I've observed some odd behavior with one of my arrays. It seems that the issue lies in how Javascript stores object references within arrays. To illustrate this problem, I'll share a code snippet that I previously posted as an answer on SO. The code simply loops through to retrieve today's date and the 6 previous dates of the month.
var dates = [];
var date = new Date();
for (var i = 0; i < 7; i++){
var tempDate = new Date();
tempDate.setDate(date.getDate()-i);
dates.push(tempDate);
}
console.log(dates);
Output:
[Thu Jun 05 2014 14:54:14 GMT+0100 (GMT Daylight Time),
Wed Jun 04 2014 14:54:14 GMT+0100 (GMT Daylight Time),
Tue Jun 03 2014 14:54:14 GMT+0100 (GMT Daylight Time),
Mon Jun 02 2014 14:54:14 GMT+0100 (GMT Daylight Time),
Sun Jun 01 2014 14:54:14 GMT+0100 (GMT Daylight Time),
Sat May 31 2014 14:54:14 GMT+0100 (GMT Daylight Time),
Fri May 30 2014 14:54:14 GMT+0100 (GMT Daylight Time)]
This is correct, and should be expected since tempDate is constantly re-created as a new Date object inside the loop.
However, when I move tempDate out of the loop, it appears to update all objects in the array each time the loop iterates (and the loop unexpectedly goes one Month and 1 day too far back to April 29th):
var dates = [];
var date = new Date();
var tempDate = new Date();
for (var i = 0; i < 7; i++){
tempDate.setDate(date.getDate()-i);
dates.push(tempDate);
}
console.log(dates);
Output:
[Tue Apr 29 2014 14:52:21 GMT+0100 (GMT Daylight Time),
Tue Apr 29 2014 14:52:21 GMT+0100 (GMT Daylight Time),
Tue Apr 29 2014 14:52:21 GMT+0100 (GMT Daylight Time),
Tue Apr 29 2014 14:52:21 GMT+0100 (GMT Daylight Time),
Tue Apr 29 2014 14:52:21 GMT+0100 (GMT Daylight Time),
Tue Apr 29 2014 14:52:21 GMT+0100 (GMT Daylight Time),
Tue Apr 29 2014 14:52:21 GMT+0100 (GMT Daylight Time)]
My two questions are:
- Why does the object stored in the array mutate with each iteration? (I suspect this could be due to Javascript storing references to the object, but an explanation would be appreciated)
- Why does the second code snippet run one iteration too far? In the first example, the loop successfully ends after 7 iterations on May 30th (7 days ago), whereas in the second example, the resulting date after the iterations falls back to April 29th - over a month in the past. Why?
Edit: I have provided a basic jsfiddle for testing the code.