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.
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"