Bagaimana cara mengekspor kelas ES6 dengan benar di Node 4?

115

Saya mendefinisikan kelas dalam modul:

"use strict";

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

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

module.export.AspectType = AspectType;

Tetapi saya mendapatkan pesan kesalahan berikut:

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

Bagaimana cara mengekspor kelas ini dan menggunakannya di modul lain? Saya telah melihat pertanyaan SO lainnya, tetapi saya mendapatkan pesan kesalahan lain ketika saya mencoba menerapkan solusi mereka.

Jérôme Verstrynge
sumber
2
Di ES6 Anda tidak perlu 'use strict'dalam modul atau kelas; ini adalah perilaku default. Ref. 10.2.1 Kode Mode Ketat
Jason Leach

Jawaban:

117

Jika Anda menggunakan ES6 di Node 4, Anda tidak dapat menggunakan sintaks modul ES6 tanpa transpiler, tetapi modul CommonJS (modul standar Node) berfungsi sama.

module.export.AspectType

seharusnya

module.exports.AspectType

karenanya pesan kesalahan "Tidak dapat menyetel properti 'AspectType' dari tidak terdefinisi" karena module.export === undefined.

Juga untuk

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

bisakah kamu menulis

class AspectType {
    // ...    
}

dan pada dasarnya mendapatkan perilaku yang sama.

loganfsmyth
sumber
27
OMG exportbukannya exports, bagaimana saya melewatkannya?
Jérôme Verstrynge
1
pada akhirnya saya letakkan module.exports = ClassNamedan berfungsi dengan baik
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
sumber
2
@sitrakay Anda benar-benar harus menambahkan penjelasan tentang bagaimana ini memperbaiki pertanyaan.
Alexis Tyler
ini memberikan kesalahan: Uncaught TypeError: Tidak dapat menetapkan ke properti hanya baca 'ekspor' dari objek '# <Object>' kenapa ini mendapat suara positif begitu banyak?
henon
Saya pikir meletakkan seluruh definisi kelas di dalam tugas ekspor adalah pola anti ketika satu baris di akhir harus melakukan hal yang sama.
pengguna1944491
44

Dengan ECMAScript 2015 Anda dapat mengekspor dan mengimpor beberapa kelas seperti ini

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

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

module.exports = {
    Person,
    Animal
};

lalu di mana Anda menggunakannya:

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

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

Jika terjadi benturan nama, atau Anda lebih suka nama lain, Anda dapat mengganti namanya seperti ini:

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

const animal = new OtherAnimal();
const person = new OtherPerson();
Jonas Brandel
sumber
1
Salah. Alasan: Jika Anda menggunakan ES6 di Node 4, Anda tidak dapat menggunakan sintaks modul ES6 tanpa transpiler, tetapi modul CommonJS (modul standar Node) berfungsi sama. (sesuai di atas)
AaronHS
Juga Anda tidak boleh mendeklarasikan dua kelas dalam file yang sama
ariel
Tidak masalah memiliki kelas "seperti pribadi" (yang membantu kelas publik tunggal) berada dalam file yang sama, selama kelas privat tidak diekspor. Ini juga dapat diterima jika Anda belum memfaktorkan ulang mereka menjadi dua file. Saat melakukannya, jangan lupa untuk membagi pengujian Anda menjadi file terpisah juga. Atau lakukan saja apa yang Anda perlukan untuk situasi Anda.
TamusJRoyce
@AaronHS apa perbedaan persis yang Anda maksud? Tidak jelas juga dalam jawaban "di atas".
pengguna1944491
16

Menggunakan

// aspect-type.js
class AspectType {

}

export default AspectType;

Kemudian untuk mengimpornya

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

Baca http://babeljs.io/docs/learn-es2015/#modules untuk detail selengkapnya

Terima kasih
sumber
1
Saya mendapatkan SyntaxError: Unexpected reserved word, dapatkah Anda memberikan contoh kode lengkap?
Jérôme Verstrynge
9
ekspor dan impor belum diimplementasikan di V8 yang digunakan node. Anda masih perlu menggunakanmodule.exports
Evan Lucas
2
... atau transpile (yaitu babel), memang. NodeJS memiliki sebagian besar fitur ES6 .. tidak termasuk import / export(masih berlaku, Mei 2017).
Frank Nocke
12

ekspresi kelas dapat digunakan untuk kesederhanaan.

 // 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);
masakielastik
sumber
4
Sekadar peringatan, di Node ini tunduk pada urutan pemuatan modul. Jadi berhati-hatilah saat menggunakan ini. Jika Anda mengganti nama file ini di sekitar contoh tidak akan berfungsi.
Dustin
12

Saya hanya menulisnya seperti ini

di file AspectType:

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

dan impor seperti ini:

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

Beberapa jawaban lain hampir sama, tetapi sejujurnya, saya pikir Anda lebih baik menggunakan sintaks yang paling bersih dan paling sederhana. OP meminta cara mengekspor kelas di ES6 / ES2015. Saya tidak berpikir Anda bisa menjadi lebih bersih dari ini:

'use strict';

export default class ClassName {
  constructor () {
  }
}
Peti
sumber
2
Salah. Alasan: Jika Anda menggunakan ES6 di Node 4, Anda tidak dapat menggunakan sintaks modul ES6 tanpa transpiler, tetapi modul CommonJS (modul standar Node) berfungsi sama. (sesuai di atas)
AaronHS
3
Siapa sih yang masih menggunakan Node 4? Saya pikir ini adalah jawaban yang valid untuk 99% orang.
Peti
Secara harfiah ada di judul pertanyaan.
AaronHS
0

Saya memiliki masalah yang sama. Apa yang saya temukan adalah saya memanggil objek penerima saya dengan nama yang sama dengan nama kelas. contoh:

const AspectType = new AspectType();

ini mengacaukan semuanya seperti itu ... semoga ini membantu

shahar taite
sumber
0

Kadang-kadang saya perlu mendeklarasikan beberapa kelas dalam satu file, atau saya ingin mengekspor kelas dasar dan tetap mengekspor namanya karena editor JetBrains saya memahami itu dengan lebih baik. Saya hanya menggunakan

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

Dan di tempat lain:

require('baseclasses.js');
class MySubclass extends MyClass() { ... }
Jelmer Jellema
sumber
1
Ini adalah cara yang buruk untuk melakukan ini ... itu akan mengakibatkan tabrakan suatu hari nanti.
Brad
Ya baiklah. Tidak ada masalah dengan tabrakan dalam proyek yang dimiliki. Dan jika Anda hanya mengimpor kelas melalui require / module.exports, Anda hanya mengalihkan masalah ke nama-modul.
Jelmer Jellema
Berhentilah mencoba menulis PHP dalam JavaScript: P Lelucon - seperti yang orang lain katakan, ini hanya menyiapkan diri Anda untuk masalah di kemudian hari. Globals adalah ide yang sangat buruk, tidak baik, sangat sangat buruk.
robertmain
1
Mereka adalah untuk orang-orang yang tidak dapat melacak kode mereka sendiri. Jangan lupa nama file yang digunakan di Require juga global. Dogma no-global juga ada batasnya.
Jelmer Jellema
Ya, @TimHobbs, hal-hal yang dikatakan anak-anak .. Hal-hal seperti "Mereka memang begitu, titik." Persis seperti itulah argumen yang Anda dengar dari orang-orang yang tidak memiliki argumen yang nyata. Kamu tahu. Bahkan NodeJ menggunakan global. Bahkan tidak ada masalah ketika Anda memiliki kerangka kerja yang terdefinisi dengan baik dengan global yang terdokumentasi dengan baik. Senang mendengar bahwa setelah bertahun-tahun belajar, lulus cum laude dan memberi makan diri saya dan keluarga saya selama 20 tahun sekarang, itu hanya "apa yang ingin saya lakukan". Beri aku argumen atau berhenti bertingkah seperti anak kecil.
Jelmer Jellema