Comment exporter correctement une classe ES6 dans Node 4?


115

J'ai défini une classe dans un module:

"use strict";

var AspectTypeModule = function() {};
module.exports = AspectTypeModule;

var AspectType = class AspectType {
    // ...    
};

module.export.AspectType = AspectType;

Mais j'obtiens le message d'erreur suivant:

TypeError: Cannot set property 'AspectType' of undefined
    at Object.<anonymous> (...\AspectType.js:30:26)
    at Module._compile (module.js:434:26)
    ....

Comment exporter cette classe et l'utiliser dans un autre module? J'ai vu d'autres questions SO, mais j'obtiens d'autres messages d'erreur lorsque j'essaye de mettre en œuvre leurs solutions.


2
Dans ES6, vous n'avez pas besoin 'use strict'd'un module ou d'une classe; c'est le comportement par défaut. Réf. 10.2.1 Code de mode strict
Jason Leach

Réponses:


117

Si vous utilisez ES6 dans Node 4, vous ne pouvez pas utiliser la syntaxe du module ES6 sans transpilateur, mais les modules CommonJS (modules standard de Node) fonctionnent de la même manière.

module.export.AspectType

devrait être

module.exports.AspectType

d'où le message d'erreur "Impossible de définir la propriété 'AspectType' sur undefined" car module.export === undefined.

Aussi pour

var AspectType = class AspectType {
    // ...    
};

pouvez-vous juste écrire

class AspectType {
    // ...    
}

et obtenir essentiellement le même comportement.


27
OMG exportau lieu de exports, comment ai-je raté ça?
Jérôme Verstrynge

1
à la fin je mets module.exports = ClassNameet ça marche bien
David Welborn

113
// person.js
'use strict';

module.exports = class Person {
   constructor(firstName, lastName) {
       this.firstName = firstName;
       this.lastName = lastName;
   }

   display() {
       console.log(this.firstName + " " + this.lastName);
   }
}

 

// index.js
'use strict';

var Person = require('./person.js');

var someone = new Person("First name", "Last name");
someone.display();

2
@sitrakay vous devriez vraiment ajouter une explication sur la façon dont cela résout la question.
Alexis Tyler

cela donne l'erreur: Uncaught TypeError: Impossible d'assigner à la propriété en lecture seule «exports» de l'objet «# <Object>» comment se fait-il que ce soit tellement voté?
henon

Je pense que mettre une définition de classe entière à l'intérieur de l'affectation des exportations est un anti-modèle lorsqu'une seule ligne à la fin devrait faire la même chose.
user1944491

44

Avec ECMAScript 2015, vous pouvez exporter et importer plusieurs classes comme celle-ci

class Person
{
    constructor()
    {
        this.type = "Person";
    }
}

class Animal{
    constructor()
    {
        this.type = "Animal";
    }
}

module.exports = {
    Person,
    Animal
};

puis où vous les utilisez:

const { Animal, Person } = require("classes");

const animal = new Animal();
const person = new Person();

En cas de collision de noms, ou si vous préférez d'autres noms, vous pouvez les renommer comme ceci:

const { Animal : OtherAnimal, Person : OtherPerson} = require("./classes");

const animal = new OtherAnimal();
const person = new OtherPerson();

1
Faux. Raison: Si vous utilisez ES6 dans Node 4, vous ne pouvez pas utiliser la syntaxe du module ES6 sans transpilateur, mais les modules CommonJS (modules standard de Node) fonctionnent de la même manière. (comme ci-dessus)
AaronHS

De plus, vous ne devriez pas déclarer deux classes dans le même fichier
ariel

Il est normal d'avoir des classes "privées" (qui aident la classe publique unique) à être dans le même fichier, tant que les classes privées ne sont pas exportées. C'est également acceptable si vous ne les avez pas encore refactorisés en deux fichiers. Ce faisant, n'oubliez pas de diviser vos tests en fichiers séparés. Ou faites simplement ce dont vous avez besoin pour votre situation.
TamusJRoyce

@AaronHS quelle est la différence exacte à laquelle vous faites référence? Ce n'est pas clair non plus dans la réponse "ci-dessus".
user1944491

16

Utilisation

// aspect-type.js
class AspectType {

}

export default AspectType;

Puis pour l'importer

// some-other-file.js
import AspectType from './aspect-type';

Lisez http://babeljs.io/docs/learn-es2015/#modules pour plus de détails


1
J'obtiens un SyntaxError: Unexpected reserved word, pouvez-vous fournir un exemple de code complet?
Jérôme Verstrynge

9
l'exportation et l'importation n'ont pas été implémentées dans le V8 utilisé par le nœud. Vous auriez encore besoin d'utilisermodule.exports
Evan Lucas

2
... ou transpile (ie babel), en effet. NodeJS a la plupart des fonctionnalités ES6 .. à l' exclusion de import / export(c'est toujours vrai, mai 2017).
Frank Nocke

12

L'expression de classe peut être utilisée pour plus de simplicité.

 // Foo.js
'use strict';

// export default class Foo {}
module.exports = class Foo {}

-

// main.js
'use strict';

const Foo = require('./Foo.js');

let Bar = new class extends Foo {
  constructor() {
    super();
    this.name = 'bar';
  }
}

console.log(Bar.name);

4
Juste un avertissement, dans Node, cela est soumis à l'ordre de chargement du module. Soyez donc prudent avec cela. Si vous changez les noms de ces fichiers, l'exemple ne fonctionnera pas.
Dustin

12

Je l'écris simplement de cette façon

dans le fichier AspectType:

class AspectType {
  //blah blah
}
module.exports = AspectType;

et importez-le comme ceci:

const AspectType = require('./AspectType');
var aspectType = new AspectType;

10

Plusieurs des autres réponses se rapprochent, mais honnêtement, je pense que vous feriez mieux d'utiliser la syntaxe la plus propre et la plus simple. Le PO a demandé un moyen d'exporter une classe dans ES6 / ES2015. Je ne pense pas que vous puissiez être plus propre que cela:

'use strict';

export default class ClassName {
  constructor () {
  }
}

2
Faux. Raison: Si vous utilisez ES6 dans Node 4, vous ne pouvez pas utiliser la syntaxe du module ES6 sans transpilateur, mais les modules CommonJS (modules standard de Node) fonctionnent de la même manière. (comme ci-dessus)
AaronHS

3
Qui diable utilise encore Node 4? Je pense que c'est une réponse valable pour 99% des gens.
Crates

C'est littéralement dans le titre de la question.
AaronHS

0

J'ai eu le même problème. Ce que j'ai trouvé, c'est que j'ai appelé mon objet récepteur du même nom que le nom de la classe. exemple:

const AspectType = new AspectType();

cela a foiré les choses de cette façon ... j'espère que cela aidera


0

Parfois, j'ai besoin de déclarer plusieurs classes dans un fichier, ou je veux exporter des classes de base et conserver leurs noms exportés car mon éditeur JetBrains comprend mieux cela. J'utilise juste

global.MyClass = class MyClass { ... };

Et ailleurs:

require('baseclasses.js');
class MySubclass extends MyClass() { ... }

1
Ceci est une mauvaise façon de le faire ... il va faire entrer en collision un jour.
Brad

Ouais bien. Aucun problème avec les collisions dans les projets possédés. Et si vous importez uniquement des classes via require / module.exports, vous déplacez simplement le problème vers les noms de module.
Jelmer Jellema

Arrêtez d'essayer d'écrire PHP en JavaScript: P Blagues à part - comme tout le monde l'a dit, il ne s'agit que de vous préparer à des problèmes plus tard. Les globaux sont une très mauvaise, pas une bonne très très mauvaise idée.
robertmain

1
Ils sont destinés aux personnes qui ne peuvent pas suivre leur propre code. N'oubliez pas que les noms de fichiers utilisés dans require sont également des noms globaux. Le dogme des non-globaux a aussi ses limites.
Jelmer Jellema

Eh bien, @TimHobbs, les choses que les enfants disent… Des trucs comme "Ils sont juste, point final." C'est exactement le genre d'arguments que vous entendez de la part des gens en l'absence d'arguments réels. Tu sais. Même NodeJs utilise des globals. Il n'y a même pas de problème lorsque vous avez un cadre bien défini avec des globaux bien documentés. Ravi d'entendre qu'après toutes ces années d'études, l'obtention du diplôme cum laude et me nourrir et nourrir ma famille depuis 20 ans maintenant, c'est juste "ce que je veux faire de toute façon". Donnez-moi une dispute ou arrêtez d'agir comme un enfant.
Jelmer Jellema
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.