views:

53

answers:

4

I noticed this situation in my code (unfortunately), and was able to duplicate it in my own JS file. So I have this code:

var date1 = new Date();  // today
var date2 = date1;

date2 = date2.setDate(date2.getDate() + 1);
// what is date1?

After this code executes, date1 is today's date + 1! This harkens back to my undergrad days when I learned about pointers, and I guess I'm a little rusty. Is that what's happening here? Obviously I've moved the assignment away from date1, and am only modifying date2, but date1 is being changed. Why is this the case?

Incidentally, after this code executes date2 is a long number like 1272123603911. I assume this is the number of seconds in the date, but shouldn't date2 still be a Date object? setDate() should return a Date object...

Thanks for the help.

+3  A: 

Classic case of Rerence Types vs. Value Types.

When the assignment operator works on primitive values (numbers, strings, Boolean, null, and undefined), a copy of the value is made. When the assignment operator works on JavaScript objects, references to the objects are copied.

Assignment by Value Versus Assignment by Reference

Therefore:

// creates a new Date object in memory with date1 as a Reference to its location
var date1 = new Date();

// date2 will now point to the same Object in memory as date1
var date2 = date1;

// Since both date1 and date2 point to the same object,
// modifying one changes the other
date2 = date2.setDate(date2.getDate() + 1);

As for the resulting value, you're correct. It's getting converted inside the expression to the number of seconds since Epoch.

Justin Niessner
Good answer, but I've never liked this "assignment by reference" terminology because to me it completely obscures the simplicity of what's going on. In Javascript (and Java), variables hold values. That's it, full stop. In the case of an object, the *value* held by the variable is a reference to (pointer to) the object, but it's still a value, there's nothing magic happening. When you do `o1 = o2`, there's no special case for objects, the value in `o2` gets put in `o1`. It's just that the value in question is a reference to the object.
T.J. Crowder
So, then if I want date1 to have its value preserved.. what then? Create date2 as a new object, and then assign date1 to it? I'm not sure how to proceed from here...
Mega Matt
+1  A: 
  • both your variables reference the same object, and the setDate() call actually changes the object itself (in other words, it doesn't just clone the original and return the new one)
  • When you use a Date object in an expression it can end up being cast to a number, which (as you say) is the number of seconds since the epoch.
Pointy
Thanks Pointy for answering the second part. What would you recommend to have date2 stay as a date object when I'm trying to advance it a day? In my example above, I'd like date2 to end up being a date object, but tomorrow's date.
Mega Matt
You can copy a date object like this: `var dateCopy=new Date(otherDate.getTime());` Then you can call `setDate()` on the second one if you like.
Pointy
+1  A: 
T.J. Crowder
+2  A: 

Your variables date1 and date2 are pointing to the same object.

That's why the when you execute the setDate on the date2 variable, you see the change on date1, because actually the two variables point to the exact same object.

    _____             ____________
   |date1| --------->| new Date();|
    ¯¯¯¯¯             ¯¯¯¯¯^¯¯¯¯¯¯
    _____                  |
   |date2| -----------------
    ¯¯¯¯¯ 

The setDate method returns the valueOf the Date object after changing it, which is a numeric representation, milliseconds since 01 January, 1970 UTC until your date.

CMS
+1 A picture is worth a thousand words.
T.J. Crowder