ES6: call class constructor without new keyword

Given a simple class

class Foo {
  constructor(x) {
    if (!(this instanceof Foo)) return new Foo(x);
    this.x = x;
  }
  hello() {
    return `hello ${this.x}`;
  }
}

Is it possible to call the class constructor without the new keyword?

Usage should allow

(new Foo("world")).hello(); // "hello world"

Or

Foo("world").hello();       // "hello world"

But the latter fails with

Cannot call a class as a function

Classes have a "class body" that is a constructor.
If you use an internal constructor() function, that function would be the same class body as well, and would be what is called when the class is called, hence a class is always a constructor.

Constructors requires the use of the new operator to create a new instance, as such invoking a class without the new operator results in an error, as it's required for the class constructor to create a new instance.

The error message is also quite specific, and correct

TypeError: Class constructors cannot be invoked without 'new'

You could;

  • either use a regular function instead of a class1.
  • Always call the class with new.
  • Call the class inside a wrapping regular function, always using new, that way you get the benefits of classes, but the wrapping function can still be called with and without the new operator2.

1)

function Foo(x) {
    if (!(this instanceof Foo)) return new Foo(x);
    this.x = x;
    this.hello = function() {
        return this.x;
    }
}

2)

class Foo {
    constructor(x) {
        this.x = x;
    }
    hello() {
        return `hello ${this.x}`;
    }
}

var _old = Foo;
Foo = function(...args) { return new _old(...args) };

As others have pointed out ES2015 spec strictly states that such call should throw TypeError, but at the same time it provides feature that can be used to achieve exactly the desired result, namely Proxies.

Proxies allows us to virtualize over a concept of an object. For instance they can be used to change some behaviour of particular object without affecting anything else.

In your specific use case class Foo is Function object which can be called -- this normally means that body of this function will be executed. But this can be changed with Proxy:

const _Foo = new Proxy(Foo, {
  // target = Foo
  apply (target, thisArg, argumentsList) {
    return new target(...argumentsList);
  }
});

_Foo("world").hello(); 
const f = _Foo("world");
f instanceof Foo; // true
f instanceof _Foo; // true

(Note that _Foo is now the class you want to expose, so identifiers should probably be the other way round)

If run by browser that support Proxies, calling _Foo(...) will now execute apply trap function instead of the orignal constructor.

At the same time this "new" _Foo class is indistinguishable from original Foo (apart from being able to call it as a normal function). Similarily there is no difference by which you can tell object created with Foo and _Foo.

The biggest downside of this is that it cannot be transpilled or pollyfilled, but still its viable solution for having Scala-like class apply in JS in the future.