Dave Peck
Dave Peck

Reputation: 1352

Javascript: syntax and the new keyword

Consider a class defined as:

class Foo { static bar() { return this; } }

I can construct an instance with new (Foo.bar())().

But new Foo.bar()() results in an Uncaught TypeError: Foo.bar is not a constructor.

Why are those extra parentheses necessary?

Upvotes: 2

Views: 94

Answers (2)

ASDFGerte
ASDFGerte

Reputation: 5195

new Foo.bar()() is identical to (new Foo.bar())().

Looking at the MDN page for operator precedence, new and a function call are in the same group. In the spec, the handling of new can be somewhat confusing. However, new will be done first.

A nice tool to check, how a specific snippet is being parsed, is https://astexplorer.net/ - it allows you to look at the AST which is the result of parsing.

The error message you get then comes from Foo.bar being a class method, which don't have [[Construct]], and cannot be used with new.

As a tip: when it is slightly unclear, how an expression will be parsed, then adding explicit braces often improves readability, even when they may not be necessary.

Upvotes: 2

Samed
Samed

Reputation: 136

  • First, you need to know what is IIFE(immediately invoked function expression). IIFE is as name suggested you can call a function immediately after declared. But JS parser should see whole as one expression.

Ex.

(function(){console.log("foo")}())

!function(){console.log("foo")}()

+function(){console.log("foo")}()

All these forces parser to see function(){console.log("foo")}() side of it as complete expression so it can call immediately.

  • Second, how new (Foo.bar())() works.

When you use new (Foo.bar())() in first parentheses returns this which is Foo itself. Because bar method is returning Foo. After second parentheses() calls it(Foo) and then new is creates a new instance of Foo. Basically you are writing new Foo() with using IIEF.

  • Third why new Foo.bar()() throws error.

When JS parser sees the expression new Foo.bar() it is immediately try creates an instance if Foo.bar and Foo.baris not a constructor. After that JS throws that error.

But if parser sees () it could throw another error that Uncaught SyntaxError: Unexpected token ')'. Because JS can not understand the what is left from that line, ().

Difference between

new Foo.bar()() and new (Foo.bar())()

same as

function(){console.log("foo")}() and (function(){console.log("foo")})()

it throws different error and stop parsing, because Foo.bar is not a constructor to call.

I hope it helps.

Some links to understand. What does the exclamation mark do before the function?

Upvotes: -1

Related Questions