Como exportar corretamente uma classe ES6 no Nó 4?


115

Eu defini uma classe em um módulo:

"use strict";

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

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

module.export.AspectType = AspectType;

Mas recebo a seguinte mensagem de erro:

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

Como devo exportar esta classe e usá-la em outro módulo? Já vi outras perguntas do SO, mas recebo outras mensagens de erro quando tento implementar suas soluções.


2
No ES6 você não precisa 'use strict'de um módulo ou classe; é o comportamento padrão. Ref. 10.2.1 Código de modo estrito
Jason Leach

Respostas:


117

Se você estiver usando ES6 no Nó 4, não poderá usar a sintaxe do módulo ES6 sem um transpiler, mas os módulos CommonJS (módulos padrão do Node) funcionam da mesma forma.

module.export.AspectType

deveria estar

module.exports.AspectType

portanto, a mensagem de erro "Não é possível definir propriedade 'AspectType' de indefinido" porque module.export === undefined.

Também para

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

você pode apenas escrever

class AspectType {
    // ...    
}

e obter essencialmente o mesmo comportamento.


27
OMG em exportvez de exports, como eu perdi isso?
Jérôme Verstrynge

1
no final eu coloquei module.exports = ClassNamee funciona bem
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 você realmente deve adicionar uma explicação de como isso corrige a questão.
Alexis Tyler

isso dá o erro: TypeError não capturado: Não é possível atribuir à propriedade somente leitura 'exportações' do objeto '# <Objeto>' por que isso é tão votado a favor?
henon

Acho que colocar uma definição de classe inteira dentro da atribuição de exportações é um antipadrão quando uma única linha no final deve fazer a mesma coisa.
user1944491

44

Com ECMAScript 2015 você pode exportar e importar várias classes como esta

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

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

module.exports = {
    Person,
    Animal
};

então onde você os usa:

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

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

Em caso de conflito de nomes, ou se preferir outros nomes, você pode renomeá-los assim:

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

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

1
Errado. Motivo: se você estiver usando ES6 no Nó 4, não poderá usar a sintaxe do módulo ES6 sem um transpiler, mas os módulos CommonJS (módulos padrão do Node) funcionam da mesma forma. (conforme acima)
AaronHS

Além disso, você não deve declarar duas classes no mesmo arquivo
ariel

Não há problema em ter classes "semelhantes a privadas" (que auxiliam a única classe pública) no mesmo arquivo, desde que as classes privadas não sejam exportadas. Também é aceitável se você ainda não os refatorou em dois arquivos. Ao fazer isso, não se esqueça de dividir seus testes em arquivos separados também. Ou apenas faça o que você precisa para sua situação.
TamusJRoyce

@AaronHS qual é a diferença exata a que você está se referindo? Também não está claro na resposta "acima".
user1944491

16

Usar

// aspect-type.js
class AspectType {

}

export default AspectType;

Então, para importá-lo

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

Leia http://babeljs.io/docs/learn-es2015/#modules para mais detalhes


1
Eu recebo um SyntaxError: Unexpected reserved word, você pode fornecer um exemplo de código completo?
Jérôme Verstrynge

9
exportação e importação não foram implementadas no V8 que o nó usa. Você ainda precisaria usarmodule.exports
Evan Lucas

2
... ou transpilar (isto é, babel), de fato. NodeJS tem a maioria dos recursos ES6 .. excluindo import / export(ainda é válido, maio de 2017).
Frank Nocke

12

expressão de classe pode ser usada para simplicidade.

 // 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
Apenas um aviso, no Node isso está sujeito à ordem de carregamento do módulo. Portanto, tenha cuidado ao usar isso. Se você trocar os nomes desses arquivos pelo exemplo, não funcionará.
Dustin

12

Eu simplesmente escrevo assim

no arquivo AspectType:

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

e importe assim:

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

10

Várias das outras respostas chegam perto, mas, honestamente, acho melhor você escolher a sintaxe mais limpa e simples. O OP solicitou um meio de exportar uma classe no ES6 / ES2015. Eu não acho que você pode ficar muito mais limpo do que isso:

'use strict';

export default class ClassName {
  constructor () {
  }
}

2
Errado. Motivo: se você estiver usando ES6 no Nó 4, não poderá usar a sintaxe do módulo ES6 sem um transpiler, mas os módulos CommonJS (módulos padrão do Node) funcionam da mesma forma. (conforme acima)
AaronHS

3
Quem diabos ainda está usando o Nó 4? Acho que essa é uma resposta válida para 99% das pessoas.
Caixas de

Está literalmente no título da pergunta.
AaronHS

0

Eu tive o mesmo problema. O que descobri foi que chamei meu objeto receptor com o mesmo nome da classe. exemplo:

const AspectType = new AspectType();

isso estragou as coisas dessa maneira ... espero que isso ajude


0

Às vezes, preciso declarar várias classes em um arquivo ou desejo exportar classes básicas e manter seus nomes exportados porque meu editor JetBrains entende isso melhor. Eu só uso

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

E em outro lugar:

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

1
Esta é uma má maneira de fazer isso ... isso vai resultar em uma colisão algum dia.
Brad

Sim, bem. Nenhum problema com colisões em projetos próprios. E se você simplesmente importar classes por meio de require / module.exports, você está apenas transferindo o problema para os nomes dos módulos.
Jelmer Jellema

Pare de tentar escrever PHP em JavaScript: P Piadas à parte - como todo mundo já disse, isso é apenas uma preparação para problemas mais tarde. Globais são uma ideia muito ruim, muito ruim, muito ruim.
robertmain

1
Eles são para pessoas que não podem rastrear seu próprio código. Não se esqueça de que os nomes de arquivo usados ​​em require também são globais. O dogma não-global também tem seus limites.
Jelmer Jellema

Bem, @TimHobbs, as coisas que as crianças dizem ... Coisas como "Eles simplesmente são, ponto final." Esse é exatamente o tipo de argumento que você ouve de pessoas que não têm argumentos reais. Você sabe. Até mesmo NodeJs usa globais. Não há problema quando você tem uma estrutura bem definida com globais bem documentados. Bom saber que depois de todos esses anos de estudo, graduação cum laude e alimentando a mim e minha família por 20 anos agora, é apenas "o que eu quero fazer de qualquer maneira". Dê-me uma discussão ou pare de agir como uma criança.
Jelmer Jellema
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.