What makes new Date() / 1000 a valid javascript?

How come I can "divide" an object by a number?

Answers:

Answer

When you execute an arithmetic operation on an object, its valueOf function is implicitly called.

Try the following to have an object that you can actually divide:

function Foo() {

    this.valueOf = function() {
        return 500;
        };

    }

var bar = new Foo();
console.log(bar/1000); // -> 0.5
Answer

Late update
Given that my answer contained some incomplete and -at times- outright wrong information, I thought it best to correct my mistakes. Albeit late, here goes:

Almost All JS objects have 23 methods in common: valueOf() in case of the date object, it maps back to the getTime() method, which returns a number. What this number is, is the number of milliseconds since jan 1st 1970, Many programming languages use this date to base their dates on. It's referred to as the Unix Timestamp, the date is called the Unix Epoch. in case you were wondering.
Another method is toString, which returns a string (obviously).
The third method is hasOwnProperty, which can be traced back in the prototype-chain to Object.prototype, but that's not important for this question.

Whenever you compare 2 values (objects or not), JS will coerce the types of both operands in such a way that the two values can be safely compared (1 == '1' coerces the string '1' to a Number, for example).
This type-coercion also applies when an object or primitive value is concatenated into a stirng, or when an expression is evaluated to a singular value (eg in your console, type new Date;, and you'll see what I mean).
The default behaviour of the Date object is to be coerced to a string, the toString method is invoked.

So, the Date instances are no different. They are objects, which means the variables' values will be references to objects. However in your expression/statement, you're using an arithmetic operator (/) on the object. A string wouldn't make much sense in this context, so JS falls back to the valueOf method (sort of, Date's can be coerced to numbers in a variety of ways). This does yield a Number, which can be divided effortlessly.
The same behaviour can be expected (and can indeed be observed) when using the comparison operators >, <, <= and >=.
This means that comparing dates, and using them to generate output is, most of the time, a doddle:

var d1 = new Date();
var d2 = new Date(1234567890123);
if (d1 > d2)
{
   //do stuff
}

When written in full, this is:

Date.prototype.valueOf = Date.prototype.getTime; //<-- this isn't how its done, but think of the valueOf method as doing something similar

if (d1.getTime() > d2.getTime()) //OR:
if (d1.valueOf() > d2.valueOf())

There are other advantages, too, apart from comparison:

var d3 = new Date(d1 - 1000); //new date, 1 second before d1

But there is a trade-off/pitfall:
As with all objects in JS, equality checks using == or === is a bit odd at first:

var a = new Date();
var b = new Date(a.valueOf());
console.log(a.toString() === b.toString());//true
console.log(a.valueOf() === b.valueOf());//true, to the milisecond
console.log(a == b);//false!
console.log(a === b);//false!!

Like I said: variables that are assigned objects don't actually hold the value of that object, they reference it. Since both a and b reference a different instance of the same object, they are not equal. Also because they're both objects (of the same type, to that) there is no type coercion going on.
Think of it as 2 houses, 100% equal in every way, except for the address. If there is no coercion, you're actually saying something like:
"There's a house on Fiction street 1, and on Fiction Street 2. Are these two houses equal?" To which the answer is a resounding no.

To fix this, you'll have to explicitly ask JS to compare the way these houses look by coercing them to another type manually. This is a lot easier than it sounds:

console.log(a.valueOf() == b.valueOf());//true
//or shorter, still:
console.log(+(a) == +(b));
//coerce to strings, either call toString, or:
console.log((''+a) == (''+b));

Again this may seem silly at first, but this way, you can at least test if two variables actually do reference the same instance. Suppose we have 2 objects taking up memory, when we really only need 1, we can free the reference to one of these instances to be GC'ed:

if (a !== b && +(a) === +(b))
{//their values are the same, but different instances
    b = a;//now b references the same object as a
}
console.log(a === b);//true
console.log(+(a) === +(b));// true again

Now there still are a few oddities, mind you, that affect the Date object in particular. Try to guess what the following statements would log:

a.setTime(a.getTime() + 1000);//add 1 second
console.log(a == (b + 1000));
console.log(a === (b + 1000));
console.log((a-1000) == b);
console.log((a-1000) === +b);

The answer is: false, false, false and true. How come?
The first case is simple: the + operator is overloaded, it also concatenates strings, and the Date object's default behaviour is to toString itself, so b+1000 is evaluated as b.toString() + '1000'.
Next, using the type and value checking === will almost always be false, since no coercion is going on.
Then, by subtracting 1000 using the not overloaded - arithmetic operator means that the left operand will still be evaluated to a number. The right operand, however will still revert to its befault behaviour of being coerced to a string. They are not equal.
The last example explicitly coerces the right operand to a number, and yields true.

To get true in all of the above cases, here's what to write

console.log(+a == (+b + 1000));
console.log(+a === (+b + 1000));
console.log((a-1000) == +b);
console.log((a-1000) === +b);

Simply explicitly coerce your Date instances and you should be OK

Answer

Because when you use the divide operator, new Date() will be converted inplicitly to an number (representing the total milliseconds of this date starting at january 1th of 1970). The + operator will not work, since + in strings means concatenation, not sum, and when you try to sum a Date it will not return the milliseconds, but the toString() of that date, but * will work since String don't have the * operator. For example, try new Date() * 2.

For more details about the Date global object, take a look here: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Date

Edit: I said that the date will be converted to a String when it is in an expression with / and I was wrong of course. I already corrected the answer. There are some comments below that can clarify even more my answer. The behavior of the String to Number still works, i.e., a String that represents a valid number can be multiplied, divided and subtracted, but not added since the sum operator is used to concatenate Strings. Take a look:

console.log( "10" + "1" );
console.log( "10" - "1" );
console.log( "10" * "2" );
console.log( "10" / "3" );

console.log( 10 + "1" );
console.log( 10 - "1" );
console.log( 10 * "2" );
console.log( 10 / "3" );

console.log( "10" + 1 );
console.log( "10" - 1 );
console.log( "10" * 2 );
console.log( "10" / 3 );
Answer

Before division date object will be converted to number which will give the milliseconds from January 1st 1970

new Date()/1000 => Number(new Date()) / 1000 = some number

Answer

Most languages actually represent Dates in their own internal language as just a number. The convention that Javascript uses is number of milliseconds since January 1, 1970, and many other languages have a similar convention. This is the same reason that you can simply subtract dates from each other in the same way that a timing method works.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.