Как правильно экспортировать класс ES6 в Node 4?


116

Я определил класс в модуле:

"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 Код строгого режима
Джейсон Лич

Ответы:


118

Если вы используете ES6 в Node 4, вы не можете использовать синтаксис модуля ES6 без транспилятора, но модули CommonJS (стандартные модули Node) работают так же.

module.export.AspectType

должно быть

module.exports.AspectType

следовательно, сообщение об ошибке «Невозможно установить свойство AspectType на undefined», потому что module.export === undefined.

Также для

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

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

class AspectType {
    // ...    
}

и получите практически такое же поведение.


27
OMG exportвместо того exports, как я это пропустил?
Жером Верстриндж

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: Невозможно назначить только для чтения свойство «exports» объекта «# <Object>», почему за это так много голосов?
henon

1
Я думаю, что размещение определения всего класса в назначении экспорта - это антипаттерн, когда одна строка в конце должна делать то же самое.
user1944491

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 в Node 4, вы не можете использовать синтаксис модуля ES6 без транспилятора, но модули CommonJS (стандартные модули Node) работают одинаково. (как указано выше)
AaronHS

Также вы не должны объявлять два класса в одном файле
Ариэль

Это нормально, если классы, подобные «частным» (которые помогают одному общедоступному классу) находиться в одном файле, если частные классы не экспортируются. Это также приемлемо, если вы еще не преобразовали их в два файла. При этом не забудьте также разделить ваши тесты на отдельные файлы. Или просто делайте то, что вам нужно в своей ситуации.
TamusJRoyce

@AaronHS, какое именно различие вы имеете в виду? В ответе "выше" тоже непонятно.
user1944491

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, вы можете предоставить полный пример кода?
Жером Верстриндж

9
экспорт и импорт не реализованы в версии 8, которую использует узел. Вам все равно нужно использовать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
Просто предупреждение, в Node это зависит от порядка загрузки модулей. Так что будьте осторожны с этим. Если вы измените имена этих файлов, пример не будет работать.
Дастин

12

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

в файле AspectType:

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

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

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

10

Некоторые другие ответы близки, но, честно говоря, я думаю, что вам лучше использовать самый чистый и простой синтаксис. OP запросил средство экспорта класса в ES6 / ES2015. Я не думаю, что вы можете стать намного чище, чем это:

'use strict';

export default class ClassName {
  constructor () {
  }
}

2
Неправильно. Причина: если вы используете ES6 в Node 4, вы не можете использовать синтаксис модуля ES6 без транспилятора, но модули CommonJS (стандартные модули Node) работают одинаково. (как указано выше)
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
Это плохой способ сделать это ... однажды это приведет к столкновению.
Брэд

Да хорошо. Нет проблем с коллизиями в собственных проектах. И если вы просто импортируете классы через require / module.exports, вы просто перекладываете проблему на имена модулей.
Jelmer Jellema

Прекратите пытаться писать PHP на JavaScript: P Шутки в сторону - как уже говорили все, это просто создает для вас проблемы в будущем. Глобалы - это очень плохая идея не очень хорошая.
robertmain

1
Они предназначены для людей, которые не могут отслеживать свой собственный код. Не забывайте, что имена файлов, используемые в require, также являются глобальными. У догмы о запрете глобальных явлений тоже есть свои пределы.
Jelmer Jellema 07

Ну, @TimHobbs, то, что говорят дети ... Такие вещи, как "Они просто есть, и точка". Именно такие аргументы можно услышать от людей, у которых нет реальных аргументов. Знаешь. Даже NodeJs использует глобальные переменные. Нет даже проблемы, когда у вас есть четко определенный фреймворк с хорошо документированными глобальными объектами. Приятно слышать, что после всех этих лет учебы, выпуска с отличием и кормления себя и своей семьи вот уже 20 лет, это просто «то, чем я все равно хочу заниматься». Дайте мне аргумент или перестаньте вести себя как ребенок.
Jelmer Jellema
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.