1

Background

I am struggling to create a function that takes a timestamp in ms from JSON and to convert it to a human-readable format. I attempted alert(Date(jsonData.timestamp).toISOString()), which resulted in "Date(...).toISOString is not a function".

But in the example for timeformating that I had looked up it worked, soon enough I noted that the pattern to be used is let myDate=new Date(...); alert(myDate.toISOString()). I tried and got an Invalid Date. So for some reason Date() and new Date() interpret the arguments differently.

I thought maybe the value I get from JSON which is a string should be passed in as a Number when I do that I end up with two different dates:

new Date(1594720804236643)); // result differs from thjsut calling Date, without new
new Date("1594720804236643")); //does not work

I figured that surly copy construciton would work and ended up with:

let myDate=Date(jsonData.timestamp);
let myDateObject=new Date(myDate);
alert(myDateObject.toISOString());

While I have a (horrible, ugly) solution, I would like to understand the nuances of new

Actual Question

Where is the difference between MyClass() and new MyClass(), a C++ programming background suggests that the difference is the only whether the object is allocated on the stack or heap. In Javascript, clearly the rules are different. On the one hand the interpretation of arguments changes, on the other hand, the set of functions available on the resulting object is different.

Saeed Hassanvand
9872 gold badges15 silver badges34 bronze badges
asked Jul 15, 2020 at 13:14
10
  • I feel that stackoverflow.com/questions/1646698/… is a good start but why the arguments passed in are treated differntly is still unclear to me. Commented Jul 15, 2020 at 13:14
  • new Date("...") expects a string in ISO8601 format Commented Jul 15, 2020 at 13:17
  • Because arguments are not typed, you can pass anything you want to any function. It may not work, but that's the function's problem at run time. The Date constructor responds to the actual parameter type on its own. Commented Jul 15, 2020 at 13:17
  • Also that number you're using to construct a Date gives a date instance in September of the year 52504. Commented Jul 15, 2020 at 13:19
  • 1
    Similarly, constructor functions can tell whether they've been invoked with new by checking the value of this explicitly. Some constructors detect that they were not called with new and respond by doing that themselves, others don't. JavaScript is truly a vastly different language from C++; it's best to not try and apply C++ reasoning to JavaScript coding. Commented Jul 15, 2020 at 13:21

1 Answer 1

1

Here's a common pattern for a constructor that, for its own design reasons, wants to behave the same way whether it's invoked with new or not:

function NewIsOptional() {
 if (this == null || !(this instanceof NewIsOptional))
 return new NewIsOptional();
 // normal constructor work
}

That trick works by checking this. If it's not bound (as would be the case if new were missing) or if it's bound to something of the wrong type, the code makes a recursive call via new. That pass through the constructor will see this properly bound to a new object, so it'll proceed to do its normal thing.

Now, not all constructor functions do that. I'm not sure I've ever written one, and I've typed in a lot of code. Some constructors throw an exception if they're not invoked via new. Some, for example the Symbol "constructor", throw an exception if they are invoked with new. Some constructors (like Date or Boolean) do completely different things when they're not invoked with new.

Basically there are no rules. A constructor is a function, and the code in the constructor can do whatever it wants. It can type check the parameter values and decide on different behaviors or decide to throw errors. It can call other functions, manipulate its closure if it was created inside one, and of course do mundane things like initialize object properties (which is the most usual thing to do).

Also, note that how a particular constructor function interprets its arguments, and how it behaves when it is or isn't invoked via new, are two completely orthogonal things. There are no rules for that either. A constructor is free to interpret arguments exactly the same with or without new, or it can interpret them completely differently. There are no fundamental language rules behind any of this.

answered Jul 16, 2020 at 12:27
4
  • This is very helpful to me I think. If I understand correctly new X() creates an Instance binding this and then executing function X on it, while I could think of a plain X() as a static method call if I would like to project Javascript onto classical object oriented programming (Which I now understand to be a bad idea...). Commented Jul 16, 2020 at 13:34
  • Is there a general rule of thumb when new should be used and when it is better to omit it, or is there no consense and one has to check for every class one wants to use? Commented Jul 16, 2020 at 13:35
  • Well that's a good question. There are people with much stronger opinions about it than I maintain. Personally I like using new because I think it adds clarity. Lots of Java people don't like it for, well, reasons I don't really get. Commented Jul 16, 2020 at 13:38
  • Also, the JavaScript world moves really fast compared with most other languages I'm familiar with. Attitudes change along with the language. Commented Jul 16, 2020 at 13:39

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.