Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 
like image 772
Mulan Avatar asked Jun 07 '15 03:06

Mulan


People also ask

Can we call constructor without new keyword?

No, this is not possible. Constructors that are created using the class keyword can only be constructed with new , if they are [[call]]ed without they always throw a TypeError 1 (and there's not even a way to detect this from the outside).

Can I call class constructor?

Simple answer: You can't.

What happens if you do not add a constructor to a class in JavaScript?

The constructor() method is called automatically when a class is initiated, and it has to have the exact name "constructor", in fact, if you do not have a constructor method, JavaScript will add an invisible and empty constructor method.

Is new keyword required in JavaScript?

The new keyword is used in javascript to create a object from a constructor function. The new keyword has to be placed before the constructor function call and will do the following things: Creates a new object. Sets the prototype of this object to the constructor function's prototype property.


1 Answers

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) }; 
like image 151
adeneo Avatar answered Sep 19 '22 23:09

adeneo