ノード4でES6クラスを適切にエクスポートする方法は?


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厳格モードコード
Jason Leach、

回答:


117

ノード4でES6を使用している場合、トランスパイラーなしでES6モジュール構文を使用することはできませんが、CommonJSモジュール(ノードの標準モジュール)は同じように機能します。

module.export.AspectType

する必要があります

module.exports.AspectType

したがって、「未定義のプロパティ 'AspectType'を設定できません」というエラーメッセージが表示されますmodule.export === undefined

また、

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

書けますか

class AspectType {
    // ...    
}

本質的に同じ動作をします。


27
OMG exportではなくexports、どうやってそれを逃したのですか?
ジェローム・Verstrynge

1
最後に私が置いたところmodule.exports = ClassName、それはうまく機能します
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あなたはこれがどのように質問を修正するかについての説明を本当に追加すべきです。
Alexis Tyler

これはエラーになります:Uncaught TypeError:オブジェクト '#<Object>'のプロパティ 'exports'を読み取り専用に割り当てることができません。
henon 2018年

クラス定義全体をexports割り当て内に配置することは、最後の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
違う。理由:ノード4でES6を使用している場合、トランスパイラーなしでES6モジュール構文を使用することはできませんが、CommonJSモジュール(ノードの標準モジュール)は同じように機能します。(上記のとおり)
AaronHS 2018

また、同じファイルで2つのクラスを宣言しないでください
ariel

プライベートクラスがエクスポートされない限り、「プライベートのような」クラス(単一のパブリッククラスを支援する)を同じファイルに含めることは問題ありません。まだ2つのファイルにリファクタリングしていない場合も許容されます。その際、テストを分割してファイルを分離することも忘れないでください。または、状況に応じて必要なことを行ってください。
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。完全なコード例を提供できますか?
ジェローム・Verstrynge

9
ノードが使用するV8では、エクスポートとインポートは実装されていません。それでも使用する必要がありますmodule.exports
Evan Lucas

2
...または実際にトランスパイル(つまり、バベル)。NodeJSは...ほとんどES6は特徴がある除く import / export(まだ2017年5月、あてはまります)。
フランクノッケ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

他のいくつかの答えは間近に迫っていますが、正直なところ、最もクリーンでシンプルな構文を使用した方がよいと思います。OPは、ES6 / ES2015でクラスをエクスポートする手段を要求しました。私はあなたがこれよりずっときれいになることができないと思います:

'use strict';

export default class ClassName {
  constructor () {
  }
}

2
違う。理由:ノード4でES6を使用している場合、トランスパイラーなしでES6モジュール構文を使用することはできませんが、CommonJSモジュール(ノードの標準モジュール)は同じように機能します。(上記のとおり)
AaronHS

3
一体誰がまだノード4を使用していますか?これは99%の人にとって有効な答えだと思います。
クレート

それは文字通り質問のタイトルにあります。
AaronHS

0

私も同じ問題を抱えていました。私が見つけたのは、受信オブジェクトにクラス名と同じ名前を付けたことです。例:

const AspectType = new AspectType();

これはその方法を台無しにしました...これが役立つことを願っています


0

JetBrainsエディターがそれをよりよく理解しているため、1つのファイルで複数のクラスを宣言する必要がある場合や、基本クラスをエクスポートしてそれらの名前をエクスポートしたままにしたい場合があります。使うだけ

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

そして他のどこか:

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

1
これは悪い方法です... いつか衝突引き起こすでしょう
ブラッド

ええ。所有プロジェクトでの衝突は問題ありません。そして、require / module.exportsを介してクラスを純粋にインポートする場合、問題をmodule-namesにシフトしているだけです。
Jelmer Jellema 2017年

JavaScriptでPHPを記述しようとするのはやめましょう。グローバルは、非常に悪い、良い、非常に悪い考えです。
robertmain

1
自分のコードを追跡できない人のためのものです。requireで使用されるファイル名もグローバルであることを忘れないでください。非グローバルのドグマにも限界があります。
Jelmer Jellema

まあ、@ TimHobbs、子供たちが言うこと..「彼らはちょうど、期間です」のようなもの。それはまさしく本当の議論のない人々からあなたが聞く種類の議論です。ええと。NodeJでもグローバルを使用します。十分に文書化されたグローバルを備えた明確に定義されたフレームワークがある場合でも、問題はありません。この数年間の勉強、20年の卒業式、そして私と私の家族への栄養補給が終わった後、それは「とにかくやりたいこと」だけだと聞いてうれしいです。議論をするか、子供のように振る舞うのをやめてください。
Jelmer Jellema 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.