¿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.


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.


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();

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();

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


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);

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;

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 () {
  }
}

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


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() { ... }

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.