Come esportare correttamente una classe ES6 nel nodo 4?


115

Ho definito una classe in un modulo:

"use strict";

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

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

module.export.AspectType = AspectType;

Ma ricevo il seguente messaggio di errore:

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

Come dovrei esportare questa classe e usarla in un altro modulo? Ho visto altre domande SO, ma ricevo altri messaggi di errore quando provo a implementare le loro soluzioni.


2
In ES6 non è necessario 'use strict'un modulo o una classe; è il comportamento predefinito. Ref. 10.2.1 Strict Mode Code
Jason Leach

Risposte:


117

Se stai usando ES6 nel nodo 4, non puoi usare la sintassi del modulo ES6 senza un transpiler, ma i moduli CommonJS (i moduli standard di Node) funzionano allo stesso modo.

module.export.AspectType

dovrebbe essere

module.exports.AspectType

da qui il messaggio di errore "Impossibile impostare la proprietà 'AspectType' di undefined" perché module.export === undefined.

Inoltre, per

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

puoi semplicemente scrivere

class AspectType {
    // ...    
}

e ottenere essenzialmente lo stesso comportamento.


27
OMG exportinvece di exports, come l'ho perso?
Jérôme Verstrynge

1
alla fine ho messo module.exports = ClassNamee funziona bene
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 dovresti davvero aggiungere una spiegazione di come questo risolve la domanda.
Alexis Tyler

questo dà l'errore: Uncaught TypeError: Impossibile assegnare alla sola lettura la proprietà 'export' dell'oggetto '# <Object>' come mai questo è così tanto upvoted?
henon

Penso che mettere un'intera definizione di classe all'interno dell'assegnazione delle esportazioni sia un anti pattern quando una singola riga alla fine dovrebbe fare la stessa cosa.
user1944491

44

Con ECMAScript 2015 puoi esportare e importare più classi come questa

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

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

module.exports = {
    Person,
    Animal
};

poi dove li usi:

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

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

In caso di collisioni di nomi, o preferisci altri nomi puoi rinominarli in questo modo:

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

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

1
Sbagliato. Motivo: se si utilizza ES6 nel nodo 4, non è possibile utilizzare la sintassi del modulo ES6 senza un transpiler, ma i moduli CommonJS (i moduli standard di Node) funzionano allo stesso modo. (come sopra)
AaronHS

Inoltre non dovresti dichiarare due classi nello stesso file
ariel

Va bene avere classi "private-like" (che aiutano la singola classe pubblica) ad essere nello stesso file, a patto che le classi private non vengano esportate. È anche accettabile se non li hai ancora rifattorizzati in due file. Quando lo fai, non dimenticare di dividere i tuoi test anche in file separati. O fai semplicemente ciò di cui hai bisogno per la tua situazione.
TamusJRoyce

@AaronHS qual è la differenza esatta a cui ti riferisci? Non è chiaro neanche nella risposta "sopra".
user1944491

16

Uso

// aspect-type.js
class AspectType {

}

export default AspectType;

Quindi importarlo

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

Leggi http://babeljs.io/docs/learn-es2015/#modules per maggiori dettagli


1
Ricevo un SyntaxError: Unexpected reserved word, potete fornire un esempio di codice completo?
Jérôme Verstrynge

9
l'esportazione e l'importazione non sono state implementate nella V8 utilizzata dal nodo. Dovresti comunque usaremodule.exports
Evan Lucas

2
... o transpile (cioè babele), appunto. NodeJS ha la maggior parte delle funzionalità ES6 .. escluso import / export(vale ancora, maggio 2017).
Frank Nocke

12

l'espressione di classe può essere utilizzata per semplicità.

 // 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
Solo un avvertimento, in Node questo è soggetto all'ordine di caricamento del modulo. Quindi fai attenzione quando usi questo. Se si cambiano i nomi di questi file nell'esempio non funzionerebbe.
Dustin

12

Lo scrivo semplicemente in questo modo

nel file AspectType:

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

e importalo in questo modo:

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

10

Molte delle altre risposte si avvicinano, ma onestamente, penso che sia meglio andare con la sintassi più pulita e semplice. Il PO ha richiesto un mezzo per esportare una classe in ES6 / ES2015. Non penso che tu possa diventare molto più pulito di questo:

'use strict';

export default class ClassName {
  constructor () {
  }
}

2
Sbagliato. Motivo: se si utilizza ES6 nel nodo 4, non è possibile utilizzare la sintassi del modulo ES6 senza un transpiler, ma i moduli CommonJS (i moduli standard di Node) funzionano allo stesso modo. (come sopra)
AaronHS

3
Chi diavolo sta ancora usando il nodo 4? Penso che questa sia una risposta valida per il 99% delle persone.
Casse

È letteralmente nel titolo della domanda.
AaronHS

0

Ho avuto lo stesso problema. Quello che ho trovato è che ho chiamato il mio oggetto di ricezione con lo stesso nome del nome della classe. esempio:

const AspectType = new AspectType();

questo ha incasinato le cose in quel modo ... spero che questo aiuti


0

A volte ho bisogno di dichiarare più classi in un file, o voglio esportare classi di base e mantenere i loro nomi esportati perché il mio editor JetBrains lo capisce meglio. Uso solo

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

E da qualche altra parte:

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

1
Questo è un brutto modo di fare questo ... è sarà il risultato in caso di collisione, un giorno.
Brad

Sì bene. Nessun problema con le collisioni nei progetti di proprietà. E se importi semplicemente classi tramite require / module.exports, stai semplicemente spostando il problema sui nomi dei moduli.
Jelmer Jellema

Smettila di provare a scrivere PHP in JavaScript: P Scherzi a parte - come hanno detto tutti gli altri, questo ti sta solo preparando per problemi in seguito. I globali sono un'idea molto cattiva, non buona, molto cattiva.
robertmain

1
Sono per le persone che non sono in grado di monitorare il proprio codice. Non dimenticare che anche i nomi dei file utilizzati in require sono globali. Anche il dogma non globale ha i suoi limiti.
Jelmer Jellema

Bene, @TimHobbs, le cose che dicono i bambini .. Cose come "Lo sono, punto." Questo è esattamente il tipo di argomenti che senti da persone in mancanza di argomenti reali. Sai. Anche NodeJs usa le globali. Non c'è nemmeno un problema quando si dispone di un framework ben definito con globali ben documentate. È bello sentire che dopo tutti questi anni di studio, laurea con lode e nutrire me stesso e la mia famiglia da 20 anni, è proprio "quello che voglio fare comunque". Dammi una discussione o smettila di comportarti come un bambino.
Jelmer Jellema
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.