Ghetolay
Ghetolay

Reputation: 3342

Why are Date treated like string with + and like number for any other arithmetic operators?

From my understanding if an object has valueOf function it will be used when object needs to be converted into a primitive. If an object has toString function it will be used when object needs to be converted into a string. So when you use + it should first use valueOf if present and then toString.

That's what it seems to do from :

var obj1 = {
  valueOf: () => 0
};

var obj2 = {
  toString: () => 'a'
};

var obj3 = { 
  valueOf: () => 0,
  toString: () => 'a'
};

obj1 + obj1; // -> 0
obj2 + obj2; // -> 'aa'
obj3 + obj3; // -> 0

Now Date is implementing both valueOf and toString like obj3 but when you do date + date you get a string !
Using any other arithmetic operators will treat date as a number do the operation and return a valid number.

Here is some code to demonstrate my confusion :

var date = new Date(2017,1,1);

date - date; // -> 0
date * date: // -> 2.20790950849296e+24
date / date; // -> 1
date % date; // -> 0
date + date; // -> "Wed Feb 01 2017 00:00:00 GMT+0100 (CET)Wed Feb 01 2017 00:00:00 GMT+0100 (CET)"

Upvotes: 1

Views: 212

Answers (3)

taha
taha

Reputation: 1017

An Object can be converted to a primitive value with the help of the Symbol.toPrimitive property (used as a function value).

The function is called with a string argument hint, which specifies the preferred type of the result primitive value. The hint argument can be one of "number", "string", and "default".

Syntax for Date objects : Date()[Symbol.toPrimitive](hint);

If hint is "string" or "default", @@toPrimitive tries to call the toString method. If the toString property does not exist, it tries to call the valueOf method and if the valueOf does not exist either, @@toPrimitive throws a TypeError.

If hint is "number", @@toPrimitive first tries to call valueOf, and if that fails, it calls toString.

var date = new Date(2017,1,1);

console.log('hint is "number":',+date + +date); // using unary plus operator
console.log('hint is "default":',date + date); // no hint (falls to hint == 'string')
console.log('hint is "string":',`${date + date}`); // using template literals

The + operator is the most confusing among all arithmetic operators. without a hint to convert the Date instance to a number, it acts as a string concatenator

Upvotes: 0

ASDFGerte
ASDFGerte

Reputation: 5193

That is because Date has an exotic @@toPrimitive which prefers string over number. See #sec-date.prototype-@@toprimitive

Date objects, are unique among built-in ECMAScript object in that they treat "default" as being equivalent to "string", All other built-in ECMAScript objects treat "default" as being equivalent to "number".

Upvotes: 1

jmargolisvt
jmargolisvt

Reputation: 6088

The + operator will act as a concatenator in JS if the first operand is a string. Since date yields a string, it will act as a concatenator in this case.

Upvotes: 0

Related Questions