115

I am defining an object like this:

function Project(Attributes, ProjectWidth, ProjectHeight)
{
    this.ProjectHeight = ProjectHeight;
    this.ProjectWidth = ProjectWidth;
    this.ProjectScale = this.GetProjectScale();
    this.Attributes = Attributes;

    this.currentLayout = '';

    this.CreateLayoutArray = function()
    {....}
}

I then try to create and instance like this:

var newProj = new Project(a,b,c);

But this execption is thrown:

Project is not a constructor

What could be wrong? I googled around a lot, but still can't figure out what I am doing wrong.

Rob W
  • 315,396
  • 71
  • 752
  • 644
unni
  • 2,471
  • 3
  • 17
  • 21
  • 1
    Out of curiosity, which browser is giving that "Project is not a constructor" message? – Dagg Nabbit Apr 11 '12 at 13:54
  • 17
    As an unrelated side node, general JavaScript style guidelines recommend starting a variable identifier with an uppercase letter only if it is a constructor: "Project" is okay, but the leading capital in "ProjectHeight" suggests to me that it should also be a constructor. If you use "projectHeight" instead, your code will be more readable to others. (In fact, if other posters are right, and you've defined a Project variable elsewhere, using the leading-uppercase-for-constructors-only rule will save you from making that mistake again.) – apsillers Apr 11 '12 at 13:55
  • @DaggNabbit Opera does (12.15) – PeerBr Jun 20 '13 at 17:39

16 Answers16

95

The code as posted in the question cannot generate that error, because Project is not a user-defined function / valid constructor.

function x(a,b,c){}
new x(1,2,3);               // produces no errors

You've probably done something like this:

function Project(a,b,c) {}
Project = {};               // or possibly   Project = new Project
new Project(1,2,3);         // -> TypeError: Project is not a constructor

Variable declarations using var are hoisted and thus always evaluated before the rest of the code. So, this can also be causing issues:

function Project(){}
function localTest() {
    new Project(1,2,3); // `Project` points to the local variable,
                        // not the global constructor!

   //...some noise, causing you to forget that the `Project` constructor was used
    var Project = 1;    // Evaluated first
}
ken
  • 3,413
  • 1
  • 25
  • 37
Rob W
  • 315,396
  • 71
  • 752
  • 644
  • In chrome, at least, there seem to be several variations of non-function/non-ctor related messages. Your example gives "TypeError: object is not a function." `new NodeList` gives "TypeError: Illegal constructor." `new Function.prototype` gives the closest thing to this the OP's message: "TypeError: function Empty() {} is not a constructor." Interesting, eh? – Dagg Nabbit Apr 11 '12 at 14:03
  • @RobW: I think in your second example the local "Project" was meant *not* to be a constructor, right? – Bergi Apr 11 '12 at 14:08
  • 2
    @RobW: Yes, but your example won't lead to a "no constructor" error, it will just use the wrong one? I thought you were about the var keyword(s), which intitializes the local scoped vars before execution of the function. – Bergi Apr 11 '12 at 14:15
69

An additional cause of this can be ES2015 arrow functions. They cannot be used as constructors.

const f = () => {};
new f(); // This throws "f is not a constructor"
vsync
  • 87,559
  • 45
  • 247
  • 317
wprl
  • 22,116
  • 10
  • 50
  • 67
39

For me it was the differences between import and require on ES6.

E.g.

// processor.js
class Processor {

}

export default Processor

//index.js
const Processor = require('./processor');
const processor = new Processor() //fails with the error

import Processor from './processor'
const processor = new Processor() // succeeds
Richard Nienaber
  • 9,247
  • 5
  • 49
  • 61
  • 2
    Works! Is there a way to make it work with `require()` function? – Raptor May 15 '19 at 17:41
  • 3
    To make the require work, you have to `require('./processor').Processor`, right? Or am I missing a special clause that does not apply to classes? – baranskistad Jun 10 '19 at 13:42
  • @baranskistad that is what bug I had, I saw `const ClassName = require("library").ClassName;` work in other code and you could instantiate the class just fine, but now I try it and it doesn't work for different code. Wondering if it's the SDK itself I'm working with. – Azurespot Sep 27 '19 at 01:22
  • @Raptor export Processor with module.exports and import with destructuring will make require() work. See my answer to this question. – Geoff Langenderfer Dec 04 '19 at 16:51
  • also make sure you've imported/required from the correct file. If you used named imports from the wrong file the variable will be `undefined` and you get the unhelpful error message. It's easy to check that your expected constructor has a value by `console.log`. – Bae Feb 11 '20 at 00:52
23

I've googled around also and found this solution:

You have a variable Project somewhere that is not a function. Then the new operator will complain about it. Try console.log(Project) at the place where you would have used it as a construcotr, and you will find it.

Bergi
  • 513,640
  • 108
  • 821
  • 1,164
18

For my project, the problem turned out to be a circular reference created by the require() calls:

y.js:
var x = require("./x.js");
var y = function() { console.log("result is " + x(); }
module.exports = y;

x.js:
var y = require("./y.js");
var my_y = new y(); // <- TypeError: y is not a constructor
var x = function() { console.log("result is " + my_y; }
module.exports = x;

The reason is that when it is attempting to initialize y, it creates a temporary "y" object (not class, object!) in the dependency system that is somehow not yet a constructor. Then, when x.js is finished being defined, it can continue making y a constructor. Only, x.js has an error in it where it tries to use the non-constructor y.

  • 1
    Thank you for posting this - just had this exact same scenario. – Jonah Jul 30 '17 at 01:09
  • Thanks for posting this! It seems I'm experiencing the same issue. How did you resolve this problem? – Gustavo Silva Dec 04 '18 at 17:28
  • If you were like me thinking that Firefox had a weird JIT bug, then this answer can give an important insight: CommonJS can't handle modules circularly referencing one another! It would be nice if my package manager (Webpack) would offer up some sort of error in the log in the circular reference case, but it did not ... instead, it broke the circular reference by returning a plain function from the require statement. CONFUSING! I was very specifically seeing this "is not a constructor" error when I was using `instanceof` operator in firefox with a circularly referenced constructor. YIKES! – DWoldrich Jan 21 '20 at 00:27
11

In my case I was using the prototype name as the object name. For e.g.

function proto1()
{}

var proto1 = new proto1();

It was a silly mistake but might be of help to someone like me ;)

Jiten
  • 305
  • 2
  • 5
10

I have a class in one file that I'm importing into a test file:

//Vec.js
class Vec {

}

module.exports.Vec = Vec;

Changing

//Vec.test.js
const Vec = require('./Vec');
const myVec = new Vec(); //TypeError: Vec is not a constructor

to

//Vec.test.js
const {Vec} = require('./Vec');
const myVec = new Vec(); //Succeeds!

resolved this error for me.

  • 1
    You're mixing es5/es6 syntax. You should really stick with one. Also, you're mixing up import functionality. In your first example, you're importing the entire module and trying to create an object from it. In you're second example you're importing just the 'Vec' class from the module, which is capable of instantiating an object. – Jamie Marshall Feb 20 '21 at 18:52
5

Sometimes it is just how you export and import it. For this error message it could be, that the default keyword is missing.

export default SampleClass {}

Where you instantiate it:

import SampleClass from 'path/to/class';
let sampleClass = new SampleClass();

Option 2, with curly braces:

export SampleClass {}
import { SampleClass } from 'path/to/class';
let sampleClass = new SampleClass();
alex351
  • 1,267
  • 1
  • 12
  • 25
4

To add to @wprl's answer, the ES6 object method shorthand, like the arrow functions, cannot be used as a constructor either.

const o = {
  a: () => {},
  b() {},
  c: function () {}
};

const { a, b, c } = o;

new a(); // throws "a is not a constructor"
new b(); // throws "b is not a constructor"
new c(); // works
Glenn Mohammad
  • 2,410
  • 2
  • 24
  • 37
4

Car.js

class Car {
 getName() {return 'car'};
}
export default Car;

TestFile.js

const object = require('./Car.js');
const instance = new object();

error: TypeError: instance is not a constructor

printing content of object

object = {default: Car}

append default to the require function and it will work as contructor

const object = require('object-fit-images').default;
const instance = new object();
instance.getName();
4

I just want to add that if the constructor is called from a different file, then something as simple as forgetting to export the constructor with

module.exports = NAME_OF_CONSTRUCTOR

will also cause the "Not a constructor" exception.

S.Norrbjörk
  • 141
  • 1
  • 4
1

In my case I'd forgotten the open and close parantheses at the end of the definition of the function wrapping all of my code in the exported module. I.e. I had:

(function () {
  'use strict';

  module.exports.MyClass = class{
  ...
);

Instead of:

(function () {
  'use strict';

  module.exports.MyClass = class{
  ...
)();

The compiler doesn't complain, but the require statement in the importing module doesn't set the variable it's being assigned to, so it's undefined at the point you try to construct it and it will give the TypeError: MyClass is not a constructor error.

Gareth
  • 141
  • 1
  • 6
1

I had a similar error and my problem was that the name and case of the variable name and constructor name were identical, which doesn't work since javascript interprets the intended constructor as the newly created variable.

In other words:

function project(name){
    this.name = name;
}

//elsewhere...

//this is no good! name/case are identical so javascript barfs. 
let project = new project('My Project');

Simply changing case or variable name fixes the problem, though:

//with a capital 'P'
function Project(name){
    this.name = name;
}

//elsewhere...

//works! class name/case is dissimilar to variable name
let project = new Project('My Project');
Colin
  • 3,770
  • 16
  • 36
1

It is happening because you must have used another variable named "project" in your code. Something like var project = {}

For you to make the code work, change as follows:

var project = {} into var project1 = {}

agrm
  • 3,296
  • 4
  • 23
  • 32
Pravin
  • 11
  • 1
  • Thanks for answering, but I don't really see how this provides something the other answers haven't already addressed. Like the [accepted answer](https://stackoverflow.com/a/10107303/2311559) from 2012. – agrm Dec 26 '17 at 18:01
0

To add the solution I found to this problem when I had it, I was including a class from another file and the file I tried to instantiate it in gave the "not a constructor" error. Ultimately the issue was a couple unused requires in the other file before the class was defined. I'm not sure why they broke it, but removing them fixed it. Always be sure to check if something might be hiding in between the steps you're thinking about.

Tathanen
  • 150
  • 1
  • 7
0

I just had a similar error when trying to use the BS5ModalJS in conjunction with webpack, meaning I was trying to import the js file.

Because the single .js file provided was designed to be used via the script tags, it took a while for me to realise that to avoid the "BSModal is not a constructor" error, I had to go into their code and add:

export {BSModal}

I was then able to use

import { BSModal } from './../thirdparty/BS5ModalJS/BS5Modal.js';

and do

let myModal enter code here= new BSModal(...)

without getting that error.

So if you're using webpack, perhaps make sure the classes and functions are exported (and therefore available) to the callers.

gmcc051
  • 190
  • 2
  • 12