0

Not much of an issue, but it falls under wat so I'm super curious.

If you make a new Date in JS and then refer to it then it returns what looks like the value of the date instead of a description of it's properties (IE: Date{date: "some date"}) like other objects do. It seems to be acting like a value instead of an object, yet it most definitely is an object. Chrome's inspector also helps to point that out with the text color change, and the lack of " " around it since it's not a string.

IE:

let date = new Date()
let person = {
  name: 'mike'
}

console.log(person) // {name:"mike"} or: Person {name:"mike"} <- obj description
console.log(person.name) // "mike" <- value

console.log(date) // Tue Jul 17 2018 22:53:29 GMT-0700 (Pacific Daylight Time) <- value?? 
// Why no description?

date.test = 'testing'
console.log(date) // Same as above, no description, but the property IS there.
console.dir(date) // Shows the object in a tree like it does with other objs.
// Note : The behavior for person is similar when used with a constructor instead of an object literal.

I know that if you excludes the new keyword and just say let date = Date() it returns a string instead, so I am guessing that the value we see when we reference it using new Date() is the object's Type or the name of it's constructor? Regardless, why don't we see the object's properties when it's referenced like we do with other objects, or at least in the same format?

Also, if you use string interpolation, IE: The current date is ${date} it also works, substituting the date into the string correctly, whereas if I tried that with the person object above it break. Using a constructor instead of an object literal would put [object Object] in the string instead.

I know in some languages like C# you can override an object's ToString() method, and that ToString() method is used as a default in string interpolation. Is something similar to that going on here?

Also curious what the Date constructor is returning. It seems like it's returning an object, and if you check typeof(date) you'll see that it's an object, but it doesn't seem to be behaving quite like other objects. At least not when it's referenced. Seems like the variable date is pointing to an object but also pointing to it's value?

However if you console.dir(date) the date, it looks like it's constructor's name is the date itself, like a dynamic constructor of some sort. Odd. Any thoughts?

tldr; Why does the Date object act differently than other objects when referenced? Should mention that it does the same thing in a REPL like Node.

Michael Treat
  • 309
  • 1
  • 3
  • 10
  • 2
    _ToString() method is used as a default in string interpolation. Is something similar to that going on here?_ Yes – Satpal Jul 18 '18 at 07:26
  • Thanks, that helps confirm my thoughts on the string interpolation, but why doesn't the object's reference show up like it does on other objects? – Michael Treat Jul 18 '18 at 07:30
  • That all depends on the implementation of your Console (for which specs have no control over). On FF, you'll see an expandable Tree with *Date 2018....* and your `test` property will be there too. Here on StackSnippet's console, they call `JSON.stringify` on the value being logged (if not an Element) – Kaiido Jul 18 '18 at 07:33
  • 2
    How the (Chrome) console displays Date objects has nothing to do with how they behave in your program. Everything is fine, as you say it's an object and it has the property. Failing to display the property on the console is an issue of the console, not of the Date object. (That said, you probably shouldn't add custom properties to date objects) – Bergi Jul 18 '18 at 07:35
  • It's not just the Chrome console. If you put it into a REPL like Node it does the same thing. – Michael Treat Jul 18 '18 at 07:38
  • `let test = date.test; console.log(test);` will log "testing". The property is inside the object. – DomeTune Jul 18 '18 at 07:38
  • Yeah, the property is definitely there, but the way the object shows up when it's referenced is different than other objects. I did that to confirm it was an object, and to confirm that it doesn't show properties on the object when you reference it like other objects do. – Michael Treat Jul 18 '18 at 07:40
  • 1
    @MichaelTreat but it's still dependent on the Console implementation... Ok Chrome is not the only one to call a simily toString() for Date objects, but that's still just their call. We could say the same for Elements for instance. In Chrome their outerHTML gets printed, while they are Objects. That's just a matter of a choice the dev-tools devs did. – Kaiido Jul 18 '18 at 07:44

2 Answers2

1

To elaborate a little bit on Satpal's comment:

JavaScript has a type coercion system with some specific rules. You can read about them here.

One of such rules is that objects coerce to numbers via their valueOf method, if such is present. If an object is coerced to a string, its toString method is called, if present, if not - its valueOf is called and the result is coerced from number to string. If neither of those methods are present, an object coerces to just a string of "[object Object]".

Console.log and string interpolation require a string, so your Date object is coerced to a string. Note the date.__proto__.toString method.

Now speaking of a constructor: everything in JavaScript is an object, including functions. So both the Date() constructor function and the object it returns via new Date() are objects. Furthermore, the .__proto__.constructor property actually refers to the constructor function, whose prototype property was used as a given object's __proto__.

To clarify things more, you should read up on JavaScript's functional inheritance, as described here.

NoSock
  • 90
  • 6
-1

It seems, that the dafault representation of data doesn't print what you spect, there is a default representation method not matching to what you want, in case you need an alternative representation of your date, you mith code something like in this example abrove How to format a JavaScript date

function formatDate(date) {
  var monthNames = [
    "January", "February", "March",
    "April", "May", "June", "July",
    "August", "September", "October",
    "November", "December"
  ];

  var day = date.getDate();
  var monthIndex = date.getMonth();
  var year = date.getFullYear();

  return day + ' ' + monthNames[monthIndex] + ' ' + year;
}

console.log(formatDate(new Date()));

Then you do a little bit of workaround

function formatDate(date) {
                  //Checking if test attribute exist, in case it does
                  //I print it
   return date + (typeof date.test === 'undefined')?'':date.test;
}
date = new Date();
date.test = 'testing'
console.log(formatDate(date));
  • Not looking to format the date. Just wondering why when you reference the object it returns the date and not the entire object's description like other objects do. – Michael Treat Jul 18 '18 at 07:43
  • thats because it carries a default representation, dates always has been a headache, formaters are the standard, unless you decide to emcapsule your date inside of an object as an atribute, that's kown as polimorfism. – Luis Hidalgo de Tena Jul 18 '18 at 07:47