¿Cómo exportar correctamente una clase ES6 en el nodo 4?

115

Definí una clase en un módulo:

"use strict";

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

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

module.export.AspectType = AspectType;

Pero recibo el siguiente mensaje de error:

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

¿Cómo debo exportar esta clase y usarla en otro módulo? He visto otras preguntas SO, pero recibo otros mensajes de error cuando trato de implementar sus soluciones.

Jérôme Verstrynge
fuente
2
En ES6 no es necesario 'use strict'en un módulo o clase; es el comportamiento predeterminado. Árbitro. 10.2.1 Código de modo estricto
Jason Leach

Respuestas:

117

Si está utilizando ES6 en el Nodo 4, no puede utilizar la sintaxis del módulo ES6 sin un transpilador, pero los módulos CommonJS (módulos estándar de Nodo) funcionan igual.

module.export.AspectType

debiera ser

module.exports.AspectType

de ahí el mensaje de error "No se puede establecer la propiedad 'AspectType' de indefinido" porque module.export === undefined.

También por

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

puedes escribir

class AspectType {
    // ...    
}

y obtienen esencialmente el mismo comportamiento.

loganfsmyth
fuente
27
Dios mío, en exportlugar de exports, ¿cómo me perdí eso?
Jérôme Verstrynge
1
al final puse module.exports = ClassNamey funciona 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();
sitrakay
fuente
2
@sitrakay, realmente debería agregar una explicación de cómo esto soluciona la pregunta.
Alexis Tyler
esto da el error: Uncaught TypeError: No se puede asignar a la propiedad de solo lectura 'exportaciones' del objeto '# <Objeto>' ¿cómo es que esto se vota tanto?
henon
Creo que poner una definición de clase completa dentro de la asignación de exportaciones es un anti patrón cuando una sola línea al final debería hacer lo mismo.
user1944491
44

Con ECMAScript 2015 puede exportar e importar varias clases como esta

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

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

module.exports = {
    Person,
    Animal
};

entonces donde los usas:

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

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

En caso de colisiones de nombres, o si prefiere otros nombres, puede cambiarles el nombre de esta manera:

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

const animal = new OtherAnimal();
const person = new OtherPerson();
Jonas Brandel
fuente
1
Incorrecto. Razón: si está usando ES6 en el Nodo 4, no puede usar la sintaxis del módulo ES6 sin un transpilador, pero los módulos CommonJS (módulos estándar del Nodo) funcionan igual. (según arriba)
AaronHS
Además, no debe declarar dos clases en el mismo archivo
ariel
Está bien tener clases "de tipo privado" (que ayuden a la clase pública única) en el mismo archivo, siempre que las clases privadas no se exporten. También es aceptable si aún no los ha refactorizado en dos archivos. Al hacerlo, no olvide dividir sus pruebas en archivos separados también. O simplemente haga lo que necesite para su situación.
TamusJRoyce
@AaronHS ¿cuál es la diferencia exacta a la que te refieres? Tampoco está claro en la respuesta "anterior".
user1944491
16

Utilizar

// aspect-type.js
class AspectType {

}

export default AspectType;

Luego para importarlo

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

Lea http://babeljs.io/docs/learn-es2015/#modules para obtener más detalles

Gracias
fuente
1
Recibo un SyntaxError: Unexpected reserved word, ¿puede proporcionar un ejemplo de código completo?
Jérôme Verstrynge
9
la exportación y la importación no se han implementado en la V8 que utiliza el nodo. Todavía necesitaría usarmodule.exports
Evan Lucas
2
... o transpile (es decir, babel), de hecho. NodeJS tiene la mayoría de las funciones de ES6 ... excluyendo import / export(todavía es válido, mayo de 2017).
Frank Nocke
12

La expresión de clase se puede utilizar para simplificar.

 // 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);
masakielástica
fuente
4
Solo una advertencia, en Node esto está sujeto al orden de carga del módulo. Así que ten cuidado al usar esto. Si cambia los nombres de estos archivos, el ejemplo no funcionaría.
Dustin
12

Simplemente lo escribo de esta manera

en el archivo AspectType:

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

e importarlo así:

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

Varias de las otras respuestas se acercan, pero honestamente, creo que es mejor optar por la sintaxis más limpia y simple. El OP solicitó un medio para exportar una clase en ES6 / ES2015. No creo que puedas ser mucho más limpio que esto:

'use strict';

export default class ClassName {
  constructor () {
  }
}
Cajas
fuente
2
Incorrecto. Razón: si está usando ES6 en el Nodo 4, no puede usar la sintaxis del módulo ES6 sin un transpilador, pero los módulos CommonJS (módulos estándar del Nodo) funcionan igual. (según arriba)
AaronHS
3
¿Quién diablos sigue usando el Nodo 4? Creo que esta es una respuesta válida para el 99% de las personas.
Crates
Está literalmente en el título de la pregunta.
AaronHS
0

Yo tuve el mismo problema. Lo que encontré fue que llamé a mi objeto receptor con el mismo nombre que el nombre de la clase. ejemplo:

const AspectType = new AspectType();

esto arruinó las cosas de esa manera ... espero que esto ayude

shahar taite
fuente
0

A veces necesito declarar varias clases en un archivo, o quiero exportar clases base y mantener sus nombres exportados porque mi editor de JetBrains lo entiende mejor. Yo solo uso

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

Y en otro lugar:

require('baseclasses.js');
class MySubclass extends MyClass() { ... }
Jelmer Jellema
fuente
1
Esta es una mala manera de hacer esto ... que va a resultar en una colisión algún día.
Brad
Sí, bueno. No hay problema con colisiones en proyectos propios. Y si simplemente importa clases a través de require / module.exports, simplemente está cambiando el problema a los nombres de los módulos.
Jelmer Jellema
Deje de intentar escribir PHP en JavaScript: P Bromas a un lado, como todos los demás han dicho, esto solo se está preparando para problemas más adelante. Los globales son una idea muy mala, nada buena, muy mala.
robertmain
1
Son para personas que no pueden rastrear su propio código. No olvide que los nombres de archivo utilizados en require también son globales. El dogma de la no globalización también tiene sus límites.
Jelmer Jellema
Bueno, @TimHobbs, las cosas que dicen los niños ... Cosas como "Simplemente son, punto". Ese es exactamente el tipo de argumentos que escuchas de personas que carecen de argumentos reales. Ya sabes. Incluso NodeJs usa globales. Ni siquiera hay un problema cuando tiene un marco bien definido con globales bien documentados. Es bueno escuchar que después de todos estos años de estudio, la graduación cum laude y alimentarme a mí y a mi familia durante 20 años, es simplemente "lo que quiero hacer de todos modos". Dame una discusión o deja de actuar como un niño.
Jelmer Jellema