121 votes

Exception Javascript "Not a Constructor" lors de la création d'objets

Je définis un objet comme ceci :

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

    this.currentLayout = '';

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

J'essaie ensuite de créer une instance comme ceci :

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

mais cette exception est levée :

Project is not a constructor

Qu'est-ce qui pourrait ne pas aller ? J'ai beaucoup cherché sur Internet, mais je n'arrive toujours pas à comprendre ce que je fais de mal.

1 votes

Par curiosité, quel navigateur donne ce message "Project is not a constructor" ?

18 votes

En tant que nœud latéral sans rapport, les directives générales de style JavaScript recommandent de commencer un identifiant de variable par une lettre majuscule uniquement s'il s'agit d'un constructeur : "Project" est correct, mais la majuscule de début dans "ProjectHeight" me suggère qu'il devrait également être un constructeur. Si vous utilisez "projectHeight" à la place, votre code sera plus lisible pour les autres. (En fait, si les autres posters ont raison, et que vous avez défini une variable Project ailleurs, l'utilisation de la règle de la majuscule initiale pour les constructeurs uniquement vous évitera de refaire cette erreur).

0 votes

@DaggNabbit Opera le fait (12.15)

103voto

Rob W Points 125904

Le code tel qu'affiché dans la question ne peut pas générer cette erreur, car Project n'est pas une fonction définie par l'utilisateur / un constructeur valide.

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

Vous avez probablement fait quelque chose comme ça :

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

Déclarations de variables à l'aide de var sont hissé et donc toujours évalué avant le reste du code. Cela peut donc également être à l'origine de problèmes :

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
}

72voto

wprl Points 6139

Une cause supplémentaire de ce problème peut être l'ES2015 fonctions de la flèche . Ils ne peuvent pas être utilisés comme constructeurs .

const f = () => {};
new f(); // This throws "f is not a constructor"

3 votes

Y a-t-il une raison particulière pour laquelle ce n'est pas le cas ?

10 votes

@Amndeep7 je pense que c'est parce que new transmet l'objet construit comme this dans la fonction constructrice, mais les fonctions flèches ont toujours l'attribut this de la portée englobante.

0 votes

Merci. J'ai oublié ce "gotcha".

41voto

Richard Nienaber Points 5049

Pour moi, c'était les différences entre import y require sur ES6.

Par exemple

processeur.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() // succeed

4 votes

Travaux ! Y a-t-il un moyen de le faire fonctionner avec require() fonction ?

4 votes

Pour que l'exigence fonctionne, vous devez require('./processor').Processor n'est-ce pas ? Ou bien ai-je oublié une clause spéciale qui ne s'applique pas aux classes ?

0 votes

@baranskistad c'est le bug que j'ai eu, j'ai vu const ClassName = require("library").ClassName; Cela fonctionnait dans un autre code et vous pouviez instancier la classe sans problème, mais maintenant j'essaie et cela ne fonctionne pas pour un autre code. Je me demande si c'est le SDK lui-même avec lequel je travaille.

25voto

Bergi Points 104242

J'ai également cherché sur Internet et trouvé cette solution :

Vous avez une variable Project quelque part qui n'est pas une fonction. Ensuite, le new l'opérateur s'en plaindra. Essayez console.log(Project) à l'endroit où vous l'auriez utilisé comme construcotr, et vous le trouverez.

18voto

Edwin Hoogerbeets Points 419

Pour mon projet, le problème s'est avéré être une référence circulaire créée par les appels require() :

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;

La raison en est que lorsqu'il tente d'initialiser y, il crée un objet "y" temporaire (pas une classe, un objet !) dans le système de dépendances qui n'est pas encore un constructeur. Ensuite, lorsque x.js a fini d'être défini, il peut continuer à faire de y un constructeur. Seulement, x.js a une erreur dans sa tentative d'utiliser le non-constructeur y.

1 votes

Merci d'avoir publié cet article. Je viens de vivre exactement le même scénario.

0 votes

Merci d'avoir posté ce message ! Il semble que je rencontre le même problème. Comment avez-vous résolu ce problème ?

0 votes

Si vous étiez comme moi en train de penser que Firefox avait un bug JIT bizarre, alors cette réponse peut donner un aperçu important : CommonJS ne peut pas gérer les modules qui se réfèrent circulairement les uns aux autres ! Ce serait bien si mon gestionnaire de paquet (Webpack) offrait une sorte d'erreur dans le journal dans le cas de référence circulaire, mais il ne l'a pas fait ... au lieu de cela, il a brisé la référence circulaire en retournant une fonction simple de la déclaration require. CONFUSION ! Je voyais très spécifiquement cette erreur "n'est pas un constructeur" lorsque j'utilisais instanceof dans firefox avec un constructeur à référence circulaire. YIKES !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X