Reputation: 830
In many languages, to invoke some function directly on new instance I need to wrap it into braces:
(new Date()).toString()
In JS new Date().toString()
and Date().toString()
give the same results as well.
Is it allowed to use function call immediately after instantiating new object in this way?
It looks like new
keyword is optional sometimes. How is this interpreted by JS engine?
Upvotes: 3
Views: 5610
Reputation: 12647
In many languages, to invoke some function directly on new instance I need to wrap it into braces Is it allowed to use function call immediately after instantiating new object in this way?
I think the problem here is potential ambiguity. While (new Date()).toString()
is clear, new Date().toString()
could (theoretically) mean either (new Date()).toString()
or new (Date().toString)()
.
But here comes operator precedence to the rescue.
the new (with argument list)
operator has a higher precedence than a function call. Therefore the order of execution in new Date().toString()
is as clear (at least to the engine) as the order in wich these math operations have to be executed 2 + 3 * 4
But beware, in JS you can also write new Date;
without the brackets, and this operator new (without argument list)
has a lower precedence than a function call. So new Date.toString()
is interpreted as new (Date.toString)()
and you get an Error that toString()
is no constructor.
It looks like new keyword is optional sometimes. How is this interpreted by JS engine?
Not at all. This ain't a JS feature this is a quirk in the implementation of these functions/classes/constructors
A bit like these implementations:
function Foo(){
if(!(this instanceof Foo))
return new Foo();
this.foo = 42;
}
//or something like
function Bar(){
return Object.create(Bar.prototype, {
bar: { value: 42 }
});
}
console.log(new Foo(), Foo());
console.log(new Bar(), Bar());
And again beware. Due to added security/failsafety you can't implement something like that with the new class
keyword. It adds (hidden) code to ensure that these constructors are always called with the new
keyword, otherwise the constructor throws an error.
Edit: For example the Array constructor works like described above, but as it seems (as pointed out in Freeman Lambdas answer) the Date constructor has (defined by the spec) two different return values, depending on wether you call it as a function or as a constructor.
Upvotes: 5
Reputation: 3655
The Date constructor is the %Date% intrinsic object and the initial value of the Date property of the global object. When called as a constructor it creates and initializes a new Date object. When Date is called as a function rather than as a constructor, it returns a String representing the current time (UTC).
// with new
const a = new Date();
console.log(typeof a); // object
console.log(a instanceof Date); // true
console.log(a.toString()); // date formatted string
// without new
const b = Date();
console.log(typeof b); // string
console.log(b instanceof Date); // false
console.log(b.toString()); // date formatted string
As you can see this behavior of Date is explicitly described in the language spec, it has nothing to do with new being optional. You can discover a lot about new just by reading through these popular questions: https://stackoverflow.com/search?q=javascript+new+keyword
Finally, you can use a newly created object immediately. There is no need to wrap it in parenthesis.
Upvotes: 2