如何在节点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

Answers:


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,您应该真正添加一个有关如何解决此问题的说明。
亚历克西斯·泰勒

这给出了错误:未捕获的TypeError:无法分配为只读对象'#<Object>'的属性'exports'怎么这么大?
亨农

我认为将整个类定义放在导出分配中是一种反模式,当末尾的一行应该做相同的事情时。
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'Apr 21'18

另外,您不应该在同一个文件中声明两个类
ariel

只要不导出私有类,就可以将“类私有”类(辅助单个公共类)放在同一文件中。如果您还没有将它们重构为两个文件,那也是可以接受的。这样做时,请不要忘记将测试也拆分为单独的文件。或者只是根据您的情况做您需要的事情。
TamusJRoyce '19

@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功能.. / 除外 (仍然适用,2017年5月)。importexport
Frank Nocke

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
错误。原因:如果在节点4中使用ES6,则没有转译器就无法使用ES6模块语法,但是CommonJS模块(节点的标准模块)的工作原理相同。(如上所述)
AaronHS'Apr 21'18

3
谁还在使用Node 4?我认为这对于99%的人来说是一个有效的答案。
板条箱

字面上是问题的标题。
AaronHS

0

我有同样的问题。我发现我将接收对象称为类名。例:

const AspectType = new AspectType();

这样把事情搞砸了...希望这会有所帮助


0

有时我需要在一个文件中声明多个类,或者由于我的JetBrains编辑器更了解这一点,所以我想导出基类并保持其名称被导出。我只是用

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

还有其他地方:

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

1
这是执行此操作的不好方法…… 有一天导致碰撞。
布拉德(Brad),

是的,很好。拥有项目中的冲突没有问题。而且,如果仅通过require / module.exports导入类,则只是将问题转移到模块名称上。
Jelmer Jellema

别再试图用JavaScript编写PHP了:P开个玩笑-就像其他所有人所说的,这只是在以后遇到问题时准备自己。全球人是一个非常糟糕的主意,不是一个好主意。
robertmain '18

1
它们用于无法跟踪自己的代码的人。不要忘记require中使用的文件名也是全局的。非全球性教条也有其局限性。
Jelmer Jellema '18年

好吧,@ TimHobbs,孩子们说的话。这正是您从缺乏真实争论的人那里听到的争论。你懂。甚至NodeJ都使用全局变量。如果您拥有一个定义良好且框架完整且文档齐全的全局变量,那么甚至没有问题。很高兴得知经过多年的学习,以优异的成绩毕业,并养活了自己和我的家人20年,这仅仅是“我想做的事情”。给我一个论点或停止像个孩子一样行事。
Jelmer Jellema '18
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.