Is there a way to prevent a new defined function to be called as constructor in JavaScript? Like throw out error when placing new
before calling it.
Asked
Active
Viewed 123 times
2

Thomson
- 20,586
- 28
- 90
- 134
-
1Just so you know, the solutions given below (except for the arrow function) are fragile in that they rely on the variable scope or prototype chains being unaltered. – Oct 16 '16 at 19:56
-
3ECMAScript 6 has a specific tool for this. You can use [`new.target`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new.target) in a function to determine if `new` was used to invoke it. `console.log(new.target)` will show `undefined` if `new` was not used, otherwise you get a reference to the function itself. – Oct 16 '16 at 19:58
3 Answers
3
You can check if a function was called with new
by seeing if it is an instance of itself
function test() {
if ( this instanceof test ) {
throw "Oh God no, not a new one !"
}
}
var a = test(); // success
var b = new test(); // fail
In ES2015 the new.target
meta property lets you check directly if new
was used to call the method
function test() {
if (new.target) {
throw "Oh God no, not a new one !"
}
}

adeneo
- 312,895
- 29
- 395
- 388
2
You could check this.constructor
inside the function:
function f() {
if (this && this.constructor === f) {
throw new Error("Don't call f as a constructor")
}
}
f(); // ok
new f(); // throws
As @squint points out, it is possible to break this check if f.prototype.constructor
is set explicitly:
f.prototype = {
constructor: "not f!"
}
new f(); // doesn't throw

joews
- 29,767
- 10
- 79
- 91
-
`f === g` in the second example, so why not use `f`? That also protects it from outside mutation when `var` or `let` are used. – Oct 16 '16 at 19:49
-
You're right, I forgot that named function expressions bind the function to its name inside the function body. – joews Oct 16 '16 at 19:51
1
If your environment supports them, you could use an arrow function:
const f = () => "test"
f() // returns "test"
new f() // throws TypeError: f is not a constructor(…)
Note that arrow functions inherit this
from the scope that they are defined in. That's different from function
(where this
usually depends on how the function is called), so you can't always use them as a drop-in replacement.
Babel currently does not throw an Exception if an arrow function is called as a constructor: Babel REPL example.

joews
- 29,767
- 10
- 79
- 91