Check if function is called with new keyword

There are multiple ways to invoke functions in JavaScript and one of the ways is with the “new” keyword calling function as a constructor. Let us see how to determine if the function is called with the “new” keyword.

Function called with new keyword

We have to cover all the edge cases when solving the problem, for example, the below implementation fails,

function A() {
    if ( (this instanceof arguments.callee) ) {
      console.log("OK, new");
    } else {
      console.log("OK, function");
    }
}
Input:
var Z = new A();
Z.lolol = A; 
Z.lolol();        

Output:
// OK, new

Even though Z.lolol(); is called as normal function it is invoked as constructor. The above code doesn’t work if you assign the constructor to the same object it has created.

Using new.target

From ES6 we can use the new.target.

As per MDN –

The new.target pseudo-property lets you detect whether a function or constructor was called using the new operator. In constructors and functions invoked using the new operator, new.target returns a reference to the constructor or function. In normal function calls, new.target is undefined.

function A(B) {
    if( new.target ) {
        console.log('OK, new');
    } else {
        console.log('OK, function');
    }
}
Input:
A(); // Ok, function
new A(); // OK, new
new A(); // Ok, new

A(4);             // OK, function
var X = new A(4); // OK, new

var Z = new A();  // OK, new
Z.lolol = A; 
Z.lolol();        // OK, function

var Y = A;
Y();              // OK, function
var y = new Y();  // OK, new
y.lolol = Y;
y.lolol();        // OK, function

Output:
"OK, function"
"OK, new"
"OK, new"
"OK, function"
"OK, new"
"OK, new"
"OK, function"
"OK, function"
"OK, new"
"OK, function"

Without new.target

We can use a flag and the instaceof method to determine if the function is called a constructor or not.

function A(B) {
    // You could use arguments.callee instead of x here,
    // except in EcmaScript 5 strict mode.
    if( this instanceof A && !this._constructed ) {
        this._constructed = true;
        console.log('OK, new');
    } else {
        console.log('OK, function');
    }
}
Input:
A(); // Ok, function
new A(); // OK, new
new A(); // Ok, new

A(4);             // OK, function
var X = new A(4); // OK, new

var Z = new A();  // OK, new
Z.lolol = A; 
Z.lolol();        // OK, function

var Y = A;
Y();              // OK, function
var y = new Y();  // OK, new
y.lolol = Y;
y.lolol();        // OK, function

Output:
"OK, function"
"OK, new"
"OK, new"
"OK, function"
"OK, new"
"OK, new"
"OK, function"
"OK, function"
"OK, new"
"OK, function"