Wie exportiere ich eine ES6-Klasse in Knoten 4 richtig?

113

Ich habe eine Klasse in einem Modul definiert:

"use strict";

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

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

module.export.AspectType = AspectType;

Aber ich bekomme folgende Fehlermeldung:

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

Wie soll ich diese Klasse exportieren und in einem anderen Modul verwenden? Ich habe andere SO-Fragen gesehen, erhalte jedoch andere Fehlermeldungen, wenn ich versuche, deren Lösungen zu implementieren.

Jérôme Verstrynge
quelle
1
In ES6 benötigen Sie kein 'use strict'Modul oder keine Klasse. Es ist das Standardverhalten. Ref. 10.2.1 Strict Mode Code
Jason Leach

Antworten:

117

Wenn Sie ES6 in Knoten 4 verwenden, können Sie die ES6-Modulsyntax nicht ohne Transpiler verwenden, aber CommonJS-Module (Standardmodule von Node) funktionieren genauso.

module.export.AspectType

sollte sein

module.exports.AspectType

daher die Fehlermeldung "Eigenschaft 'AspectType' von undefined kann nicht festgelegt werden", weil module.export === undefined.

Auch für

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

kannst du einfach schreiben

class AspectType {
    // ...    
}

und erhalten im Wesentlichen das gleiche Verhalten.

loganfsmyth
quelle
27
OMG exportstatt exports, wie habe ich das vermisst?
Jérôme Verstrynge
1
Am Ende habe ich gesetzt module.exports = ClassNameund es funktioniert gut
David Welborn
112
// 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();
Sitrakay
quelle
2
@sitrakay Sie sollten wirklich eine Erklärung hinzufügen, wie dies die Frage behebt.
Alexis Tyler
Dies gibt den Fehler aus: Nicht gefangener TypError: Kann nicht der schreibgeschützten Eigenschaft 'Exporte' des Objekts '# <Objekt>' zuweisen. Wie kommt es, dass dies so stark verbessert wird?
Henon
Ich denke, eine vollständige Klassendefinition in die Exportzuweisung einzufügen, ist ein Anti-Muster, wenn eine einzelne Zeile am Ende dasselbe tun sollte.
user1944491
43

Mit ECMAScript 2015 können Sie mehrere Klassen wie diese exportieren und importieren

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

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

module.exports = {
    Person,
    Animal
};

dann, wo Sie sie verwenden:

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

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

Bei Namenskollisionen oder wenn Sie andere Namen bevorzugen, können Sie diese wie folgt umbenennen:

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

const animal = new OtherAnimal();
const person = new OtherPerson();
Jonas Brandel
quelle
1
Falsch. Grund: Wenn Sie ES6 in Knoten 4 verwenden, können Sie die ES6-Modulsyntax nicht ohne Transpiler verwenden, aber CommonJS-Module (Standardmodule von Node) funktionieren genauso. (wie oben)
AaronHS
Außerdem sollten Sie nicht zwei Klassen in derselben Datei deklarieren
Ariel
Es ist in Ordnung, "private" Klassen (die die einzelne öffentliche Klasse unterstützen) in derselben Datei zu haben, solange die privaten Klassen nicht exportiert werden. Es ist auch akzeptabel, wenn Sie sie noch nicht in zwei Dateien umgestaltet haben. Vergessen Sie dabei nicht, Ihre Tests auch in separate Dateien aufzuteilen. Oder tun Sie einfach, was Sie für Ihre Situation brauchen.
TamusJRoyce
@AaronHS Was ist der genaue Unterschied, auf den Sie sich beziehen? Es ist auch in der "obigen" Antwort nicht klar.
user1944491
16

Verwenden

// aspect-type.js
class AspectType {

}

export default AspectType;

Dann importieren

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

Weitere Informationen finden Sie unter http://babeljs.io/docs/learn-es2015/#modules

Danke dir
quelle
1
Ich bekomme eine SyntaxError: Unexpected reserved word, können Sie ein vollständiges Codebeispiel bereitstellen?
Jérôme Verstrynge
9
Export und Import wurden in der vom Knoten verwendeten Version 8 nicht implementiert. Sie müssten noch verwendenmodule.exports
Evan Lucas
2
... oder transpile (dh babel), in der Tat. NodeJS hat die meisten ES6 verfügt .. ohne import / export(gilt nach wie vor, im Mai 2017).
Frank Nocke
12

Der Klassenausdruck kann der Einfachheit halber verwendet werden.

 // 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);
masakielastisch
quelle
4
Nur eine Warnung, in Node unterliegt dies der Ladereihenfolge des Moduls. Seien Sie also vorsichtig damit. Wenn Sie die Namen dieser Dateien im Beispiel ändern, funktioniert dies nicht.
Dustin
12

Ich schreibe es einfach so

in der AspectType-Datei:

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

und importiere es so:

const AspectType = require('./AspectType');
var aspectType = new AspectType;
Behnam Ghiaseddin
quelle
10

Einige der anderen Antworten kommen nahe, aber ehrlich gesagt denke ich, dass Sie besser mit der saubersten und einfachsten Syntax arbeiten sollten. Das OP forderte ein Mittel zum Exportieren einer Klasse in ES6 / ES2015 an. Ich glaube nicht, dass Sie viel sauberer werden können:

'use strict';

export default class ClassName {
  constructor () {
  }
}
Kisten
quelle
2
Falsch. Grund: Wenn Sie ES6 in Knoten 4 verwenden, können Sie die ES6-Modulsyntax nicht ohne Transpiler verwenden, aber CommonJS-Module (Standardmodule von Node) funktionieren genauso. (wie oben)
AaronHS
3
Wer zum Teufel benutzt noch Knoten 4? Ich denke, dies ist eine gültige Antwort für 99% der Menschen.
Kisten
Es steht buchstäblich im Titel der Frage.
AaronHS
0

Ich hatte das gleiche Problem. Was ich fand, war, dass ich mein empfangendes Objekt den gleichen Namen wie den Klassennamen nannte. Beispiel:

const AspectType = new AspectType();

das hat die Dinge so vermasselt ... hoffe, das hilft

Shahar Taite
quelle
0

Manchmal muss ich mehrere Klassen in einer Datei deklarieren, oder ich möchte Basisklassen exportieren und ihre Namen exportieren lassen, da mein JetBrains-Editor dies besser versteht. Ich benutze nur

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

Und woanders:

require('baseclasses.js');
class MySubclass extends MyClass() { ... }
Jelmer Jellema
quelle
1
Dies ist ein schlechter Weg, dies zu tun ... es wird eines Tages zu einer Kollision führen.
Brad
Nun ja. Kein Problem mit Kollisionen in eigenen Projekten. Und wenn Sie Klassen nur über require / module.exports importieren, verschieben Sie das Problem nur auf die Modulnamen.
Jelmer Jellema
Hören Sie auf, PHP in JavaScript zu schreiben: P Witze beiseite - wie alle anderen gesagt haben, bereitet sich dies nur auf spätere Probleme vor. Globals sind eine sehr schlechte, keine gute, sehr, sehr schlechte Idee.
Robertmain
1
Sie sind für Leute gedacht, die ihren eigenen Code nicht verfolgen können. Vergessen Sie nicht, dass die in require verwendeten Dateinamen auch global sind. Das No-Globals-Dogma hat auch seine Grenzen.
Jelmer Jellema
Nun, @TimHobbs, die Dinge, die Kinder sagen. Sachen wie "Sie sind einfach, Punkt." Das ist genau die Art von Argumenten, die Sie von Menschen hören, denen echte Argumente fehlen. Wissen Sie. Sogar NodeJs verwenden Globals. Es gibt nicht einmal ein Problem, wenn Sie ein gut definiertes Framework mit gut dokumentierten Globals haben. Schön zu hören, dass es nach all den Jahren des Studiums, des Abschlusses und der Ernährung von mir und meiner Familie seit 20 Jahren nur "das ist, was ich sowieso tun möchte". Gib mir einen Streit oder hör auf, dich wie ein Kind zu benehmen.
Jelmer Jellema