2

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.

2
  • 1
    Just 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. Commented Oct 16, 2016 at 19:56
  • 3
    ECMAScript 6 has a specific tool for this. You can use 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. Commented Oct 16, 2016 at 19:58

3 Answers 3

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 !"
    }
}
Sign up to request clarification or add additional context in comments.

Comments

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 

2 Comments

f === g in the second example, so why not use f? That also protects it from outside mutation when var or let are used.
You're right, I forgot that named function expressions bind the function to its name inside the function body.
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.

Arrow function compatibility table

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.