275

I have seen objects being created this way:

const obj = new Foo;

But I thought that the parentheses are not optional when creating an object:

const obj = new Foo();

Is the former way of creating objects valid and defined in the ECMAScript standard? Are there any differences between the former way of creating objects and the later? Is one preferred over the other?

Michał Perłakowski
  • 88,409
  • 26
  • 156
  • 177
Behrang
  • 46,888
  • 25
  • 118
  • 160
  • http://www.ecma-international.org/ecma-262/5.1/#sec-11.2.2 – SheetJS Aug 14 '13 at 09:32
  • Updated reference: ECMAScript 2017 [*§12.3.3 The new Opertator*](http://ecma-international.org/ecma-262/8.0/#sec-new-operator). – RobG Jul 31 '17 at 03:40
  • 1
    **TL;DR:** *Beware* that `new a.b()` is different from `new a().b()`, in that, in the former case, `a.b` is first accessed, whereas in the latter case, a new `a` is created first. – Andrew Apr 15 '20 at 00:46

6 Answers6

273

Quoting David Flanagan1:

As a special case, for the new operator only, JavaScript simplifies the grammar by allowing the parenthesis to be omitted if there are no arguments in the function call. Here are some examples using the new operator:

o = new Object;  // Optional parenthesis omitted here
d = new Date();  

...

Personally, I always use the parenthesis, even when the constructor takes no arguments.

In addition, JSLint may hurt your feelings if you omit the parenthesis. It reports Missing '()' invoking a constructor, and there doesn't seem to be an option for the tool to tolerate parenthesis omission.


1 David Flanagan: JavaScript the Definitive Guide: 4th Edition (page 75)

Community
  • 1
  • 1
Daniel Vassallo
  • 337,827
  • 72
  • 505
  • 443
  • 8
    Why does JSLint encourage the use of parenthesis? – Randomblue Dec 27 '11 at 03:07
  • 12
    I guess it is just considered more consistent. – Daniel Vassallo Dec 28 '11 at 13:26
  • 14
    I find it interesting to see that many JavaScript developers use parentheses simply because "the tool (JSLint) told them to do so", especially considering that the examples on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Details_of_the_Object_Model , from "the guys who invented the language" don't use any parentheses on `new Class` for parameterless constructors. If this doesn't spell 'opinionated', I don't know what does... – ack Mar 02 '14 at 05:37
  • 63
    @ack Well, it would be odd *not* to see the language's inventors showcase certain features of their language (in this case, the option to omit parentheses on constructors). If they hadn't added the feature, we wouldn't be asking whether it should be used in the first place. A practical reason for not using it is this: `new Object.func()` is NOT equivalent to `new Object().func()`. By always including parentheses, the possibility of making this mistake is eliminated. – nmclean Apr 01 '14 at 18:00
  • 2
    If you want to eliminate the possibility of making a mistake you should use ```(new Object).func()```. But I consider using extra parenthesis and extra equal signs, as in ```==``` vs ```===```, a bad excuse for not learning your language. – Jean Vincent Jun 02 '17 at 12:26
  • I think this "feature" is more of an artefact of how the grammar is parsed and interpreted rather than a deliberate attempt to "simplify" the language. *new* can only be followed by a constructor, so if that condition is satisfied then no arguments are required and sufficient information is known to process the instructions. Not so with a function name without *new*: the `()` means call the function, omitting `()` means just get a reference. – RobG Aug 01 '17 at 05:40
  • JS is such a wired language, full of exceptions. – lxmfly123 Oct 22 '17 at 07:07
  • What about `(new Date).getDay()`? –  May 07 '18 at 15:17
  • As a side note one may omit `()` in the same way also in C++ and it's completely normal. In my opinion chaining things like `new Object().func()` is a bad practice anyway. – juzzlin Dec 19 '20 at 21:05
107

There are differences between the two:

  • new Date().toString() works perfectly and returns the current date
  • new Date.toString() throws "TypeError: Date.toString is not a constructor"

It happens because new Date() and new Date have different precedence. According to MDN the part of JavaScript operator precedence table we are interested in looks like:

Precedence Operator type Associativity Operators
18 Member Access
Computed Member Access
new (with argument list)
left-to-right
left-to-right
n/a
… . …
… [ … ]
new … ( … )
17 Function Call
new (without argument list)
left-to-right
right-to-left
… ( … )
new …

From this table follows that:

  1. new Foo() has higher precedence than new Foo

    new Foo() has the same precedence as . operator

    new Foo has one level lower precedence than the . operator

    new Date().toString() works perfectly because it evaluates as (new Date()).toString()

    new Date.toString() throws "TypeError: Date.toString is not a constructor" because . has higher precedence than new Date (and higher then "Function Call") and the expression evaluates as (new (Date.toString))()

    The same logic can be applied to … [ … ] operator.

  2. new Foo has right-to-left associativity and for new Foo() "associativity" isn't applicable. I think in practice it doesn't make any difference. For additional information see this SO question


Is one preferred over the other?

Knowing all that, it can be assumed that new Foo() is preferred.

Donald Duck
  • 8,409
  • 22
  • 75
  • 99
traxium
  • 2,701
  • 2
  • 16
  • 17
  • 11
    Finally, someone who actually answers the question and points out the subtle difference! – gcampbell Jul 07 '16 at 12:38
  • wow, thanks. reminds me of another language https://en.wikipedia.org/wiki/Brainfuck – John Henckel Jul 11 '16 at 14:22
  • Well explained, offers exactly the reason why `new Foo()` should be preferred over `new Foo`. The best answer so far. – CodeLama Jul 27 '16 at 07:03
  • Awesome answer, the precedence table and accompanying explanation makes it completely clear. Glad you explain how that makes it alright to write `new Object().something()` as well as `(new Object()).something()`. – LittleTiger Aug 10 '16 at 01:50
  • 1
    Great explanation but I disagree with the conclusion and still think not using parenthesis is just fine if you know your language. BTW if you don't know JS precedence you could also use ```(new Date).toString()```, same character count, and more explicit than ```new Date().toString```. – Jean Vincent Jun 02 '17 at 12:22
  • The explanation on chaining answers this question - https://stackoverflow.com/q/55545175/1828637 - thanks. And @JeanVincent also adds to the answer for this question. – Noitidart Apr 06 '19 at 13:34
  • The right-to-left associativity makes `new new foo` parse as `new (new foo)` rather than `(new new) foo` which makes it possible to make a `function wat () { wat.counter = 1 + (wat.counter ? wat.counter : 0); return wat; }` which counts the total number of `new`s used on the `wat` constructor. You can do `console.log(new new new new wat) // -> [Function: wat] {counter: 4}`... but why. – T Tse Nov 05 '20 at 08:51
14

I don't think there is any difference when you are using the "new" operator. Be careful about getting into this habit, as these two lines of code are NOT the same:

var someVar = myFunc; // this assigns the function myFunc to someVar
var someOtherVar = myFunc(); // this executes myFunc and assigns the returned value to someOtherVar
jbabey
  • 45,965
  • 12
  • 71
  • 94
13

If you do not have arguments to pass, the parentheses are optional. Omitting them is just syntactic sugar.

Josh
  • 6,155
  • 2
  • 22
  • 26
8

https://262.ecma-international.org/6.0/#sec-new-operator-runtime-semantics-evaluation

Here's the part of the ES6 spec that defines how the two variants operate. The no-parentheses variant passes an empty argument list.

Interestingly, the two forms have different grammatical meanings. This comes up when you try to access a member of the result.

new Array.length // fails because Array.length is the number 1, not a constructor
new Array().length // 0
ParkerM
  • 302
  • 1
  • 4
  • 17
guest
  • 6,450
  • 30
  • 44
  • It's defined well in ES5 and ES3 too - "Return the result of calling the [[Construct]] internal method on constructor, providing no arguments (that is, an empty list of arguments)." – Benjamin Gruenbaum May 29 '14 at 00:10
2

There's no difference between the two.

Ivan
  • 10,052
  • 12
  • 47
  • 78