Ingo Kegel
Ingo Kegel

Reputation: 48090

Inconsistent conversion of JavaScript Date objects by arithmetic operators

What Javascript language rule leads to the following conversion weirdness?

new Date() - 2 => number
new Date() * 2 => number
new Date() / 2 => number

but

new Date() + 2 => string

I had thought that the + operator would use the valueOf() method of the Date object to convert it to a number. Like in the following example:

{valueOf: function() {return 1;}} + 2 => number

What is different in the case of a Date?

Upvotes: 2

Views: 229

Answers (3)

Ingo Kegel
Ingo Kegel

Reputation: 48090

After studying the Javascript spec, there is indeed a special case for Date objects in the context of the addition operator:

http://ecma-international.org/ecma-262/5.1/#sec-11.6.1

Conversion of a Date object is handled differently than for other objects:

No hint is provided in the calls to ToPrimitive in steps 5 and 6. All native ECMAScript objects except Date objects handle the absence of a hint as if the hint Number were given; Date objects handle the absence of a hint as if the hint String were given.

I think I understand the motivation, but as a language rule, this feels quite ugly.

Upvotes: 0

Fabrizio Calderan
Fabrizio Calderan

Reputation: 123397

when you try to do

new Date() + 2  

you're doing a string concatenation (so new Date() is returning a string representation of the Date object equivalent to (new Date()).toString()),

In the in other cases you're using an arithmetic operator (and in this case new Date() returns the milliseconds from "Epoch")

To have a "consistent" behaviour make a type coercion just using +(new Date()) so that

+(new Date()) - 2 => number
+(new Date()) * 2 => number
+(new Date()) / 2 => number
+(new Date()) + 2 => number

Upvotes: 3

Elias Van Ootegem
Elias Van Ootegem

Reputation: 76433

It's not inconsistent: Just try d = new Date(); console.log(d); the toString method, that is implicitly invoked in the above code returns a string by default. Since JS is loosely typed, and + is an overloaded operator (concatenates strings, and does arithmetic), both the date object and the int (2) are coerced:

I guess the logic behind this is something like: if neither operand is directly compatible, both are coerced to a third type: sort of "Meeting each other half-way". Dates are converted to strings by default, and a number can do that, too, so JS assumes that is what you want (it being the most logic interpretation).
The other examples use different operands, that leave no room for interpretation, hence the date-object's numeric value is used

It's an easy fix, though:

+(new Date()) + 2;//+ coerces new Date() to int

Here's some more info

Upvotes: 1

Related Questions