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.
1 Answer 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.
-
This is very helpful to me I think. If I understand correctly
new X()
creates an Instance bindingthis
and then executing functionX
on it, while I could think of a plainX()
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...).ted– ted2020年07月16日 13:34:11 +00:00Commented 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?ted– ted2020年07月16日 13:35:52 +00:00Commented 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.Pointy– Pointy2020年07月16日 13:38:33 +00:00Commented 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.Pointy– Pointy2020年07月16日 13:39:37 +00:00Commented Jul 16, 2020 at 13:39
new Date("...")
expects a string in ISO8601 formatnew
by checking the value ofthis
explicitly. Some constructors detect that they were not called withnew
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.