Як правильно експортувати клас ES6 в Node 4?


115

Я визначив клас у модулі:

"use strict";

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

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

module.export.AspectType = AspectType;

Але я отримую таке повідомлення про помилку:

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

Як слід експортувати цей клас та використовувати його в іншому модулі? Я бачив інші питання SO, але я отримую інші повідомлення про помилки, коли намагаюся реалізувати їхні рішення.


2
У ES6 вам не потрібен 'use strict'модуль чи клас; його поведінка за замовчуванням. Реф. 10.2.1 Код суворого режиму
Джейсон Ліч

Відповіді:


117

Якщо ви використовуєте ES6 у Вузлі 4, ви не можете використовувати синтаксис модулів ES6 без транспілятора, але модулі CommonJS (стандартні модулі Вузла) працюють однаково.

module.export.AspectType

має бути

module.exports.AspectType

отже, повідомлення про помилку "Неможливо встановити властивість" AspectType "невизначеного", оскільки module.export === undefined.

Також для

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

ти можеш просто написати

class AspectType {
    // ...    
}

і отримати по суті таку саму поведінку.


27
OMG exportзамість того exports, як я це пропустив?
Jérôme Verstrynge

1
наприкінці я поставив, module.exports = ClassNameі це прекрасно працює
Девід Уелборн

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 ви дійсно повинні додати пояснення, як це вирішує питання.
Алексіс Тайлер

це дає помилку: Uncaught TypeError: Неможливо призначити для зчитування лише властивості "експортування" об'єкта "# <Object>", чому це так сильно оцінено?
henon

Я думаю, що визначення визначення класу всередині призначення для експорту - це анти-шаблон, коли один рядок в кінці повинен робити те саме.
користувач1944491

44

За допомогою ECMAScript 2015 ви можете експортувати та імпортувати декілька подібних класів

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

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

module.exports = {
    Person,
    Animal
};

то де ви їх використовуєте:

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

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

У випадку зіткнення імен або ви віддаєте перевагу іншим іменам, ви можете перейменувати їх так:

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

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

1
Неправильно. Причина: Якщо ви використовуєте ES6 у Вузлі 4, ви не можете використовувати синтаксис модулів ES6 без транспілера, але CommonJS модулі (стандартні модулі Вузла) працюють однаково. (відповідно до вище)
AaronHS

Також не слід оголошувати два класи в одному файлі
аріель,

Добре, щоб "приватно-схожі" класи (які допомагають одному загальнодоступному класу) знаходилися в одному файлі, доки приватні класи не експортуються. Це також прийнятно, якщо ви ще не переробили їх у два файли. Роблячи це, не забудьте розділити свої тести і на окремі файли. Або просто зробіть те, що потрібно для вашої ситуації.
TamusJRoyce

@AaronHS, яка саме різниця, на яку ви посилаєтесь? Невідомо і у відповіді "вище".
користувач1944491

16

Використовуйте

// aspect-type.js
class AspectType {

}

export default AspectType;

Потім імпортувати його

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

Читайте http://babeljs.io/docs/learn-es2015/#modules для отримання більш докладної інформації


1
Я отримую SyntaxError: Unexpected reserved word, чи можете ви навести повний приклад коду?
Jérôme Verstrynge

9
експорт та імпорт не реалізовані у V8, який використовує вузол. Вам все одно доведеться користуватисяmodule.exports
Еван Лукас

2
... або трансліл (тобто вавило). NodeJS має більшість функцій ES6 .. виключаючи import / export(все ще справедливо, травень 2017 року).
Френк Нокк

12

вираз класу може бути використаний для простоти.

 // 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
Лише попередження, у Вузлі це підпорядковується порядку завантаження модуля. Тому будьте обережні з використанням цього. Якщо ви переключите назви цих файлів навколо прикладу, це не спрацює.
Дастін

12

Я просто пишу це так

у файлі AspectType:

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

і імпортувати його так:

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

10

Декілька інших відповідей наближаються, але, чесно кажучи, я думаю, що вам краще піти з найчистішим, найпростішим синтаксисом. ОП вимагала засоби експорту класу в ES6 / ES2015. Я не думаю, що ти можеш отримати набагато чистіше, ніж це:

'use strict';

export default class ClassName {
  constructor () {
  }
}

2
Неправильно. Причина: Якщо ви використовуєте ES6 у Вузлі 4, ви не можете використовувати синтаксис модулів ES6 без транспілера, але CommonJS модулі (стандартні модулі Вузла) працюють однаково. (відповідно до вище)
AaronHS

3
Хто до біса все ще використовує Node 4? Я думаю, що це правильна відповідь для 99% людей.
Crates

Це буквально в назві питання.
AaronHS

0

У мене була така ж проблема. Що я знайшов, я назвав мій приймаючий об'єкт тим же ім'ям, що і ім'я класу. приклад:

const AspectType = new AspectType();

це накручувало речі таким чином ... сподіваюся, що це допомагає


0

Іноді мені потрібно оголосити кілька класів в одному файлі, або я хочу експортувати базові класи та зберігати їхні імпорти, експортовані через те, що мій редактор JetBrains розуміє це краще. Я просто використовую

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

А ще десь:

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

1
Це поганий спосіб зробити це ... це призведе до зіткнення в якийсь день.
Бред

Так добре. Немає проблем із зіткненнями у власних проектах. І якщо ви просто імпортуєте класи через requ / module.exports, ви просто перекладаєте проблему на назви модулів.
Jelmer Jellema

Перестаньте намагатись писати PHP на JavaScript: P Помітає сторону - як і всі інші сказали, це просто налаштування себе на проблеми пізніше вниз. Глобали - це дуже погано, не дуже, дуже погано.
robertmain

1
Вони призначені для людей, які не можуть відстежувати власний код. Не забувайте, що назви файлів, які використовуються в запиті, також є глобальними. Догма неглобалів також має свої межі.
Джелмер Джеллема

Ну, @TimHobbs, речі, про які говорять діти .. Речі на кшталт "Вони просто є, період". Саме такий аргумент ви чуєте від людей за браком реальних аргументів. Ти знаєш. Навіть NodeJs використовує глобали. Не існує навіть проблеми, коли у вас чітко визначені рамки з добре задокументованими глобалами. Приємно почути, що після всіх цих років навчання, закінчення навчання та закінчення годування себе та моєї родини вже 20 років, це просто "те, що я хочу робити все одно". Дайте мені аргумент або перестаньте діяти, як дитина.
Jelmer Jellema
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.