160

I defined a class in a module:

"use strict";

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

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

module.export.AspectType = AspectType;

But I get the following error message:

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

How should I export this class and use it in another module? I have seen other SO questions, but I get other error messages when I try to implement their solutions.

1
  • 3
    In ES6 you don't need 'use strict' in a module or class; its the default behaviour. Ref. 10.2.1 Strict Mode Code Commented Nov 14, 2016 at 0:25

9 Answers 9

165
// 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();
Sign up to request clarification or add additional context in comments.

4 Comments

@sitrakay you should really add an explanation of how this fixes the question.
this gives the error: Uncaught TypeError: Cannot assign to read only property 'exports' of object '#<Object>' how come this is upvoted so much?
I think putting an entire class definition inside the exports assignment is an anti pattern when a single line at the end should do the same thing.
in my case, the display function is not exported unless in the constructor I wrote this.display = display, any idea why?
138

If you are using ES6 in Node 4, you cannot use ES6 module syntax without a transpiler, but CommonJS modules (Node's standard modules) work the same.

module.export.AspectType

should be

module.exports.AspectType

hence the error message "Cannot set property 'AspectType' of undefined" because module.export === undefined.

Also, for

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

can you just write

class AspectType {
    // ...    
}

and get essentially the same behavior.

2 Comments

OMG export instead of exports, how did I miss that?
at the end I put module.exports = ClassName and it works fine
82

With ECMAScript 2015 you can export and import multiple classes like this

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

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

module.exports = {
    Person,
    Animal
};

then where you use them:

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

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

In case of name collisions, or you prefer other names you can rename them like this:

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

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

4 Comments

Wrong. Reason: If you are using ES6 in Node 4, you cannot use ES6 module syntax without a transpiler, but CommonJS modules (Node's standard modules) work the same. (as per above)
Also you shouldn't declare two classes in the same file
It is okay to have "private-like" classes (that assist the single public class) to be in the same file, as long as the private classes aren't exported. It is also acceptable if you haven't yet refactored them into two files yet. When doing so, don't forget to split your tests to separate files too. Or just do what you need to for your situation.
@AaronHS what is the exact difference to which you're referring? It's not clear in the "above" answer either.
23

Use

// aspect-type.js
class AspectType {

}

export default AspectType;

Then to import it

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

Read http://babeljs.io/docs/learn-es2015/#modules for more details

3 Comments

I get a SyntaxError: Unexpected reserved word, can you provide a full code example?
export and import have not been implemented in the V8 that node uses. You would still need to use module.exports
...or transpile (i.e. babel), indeed. NodeJS has most ES6 features.. excluding import/export (still holds true, May 2017).
18

I simply write it this way

in the AspectType file:

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

and import it like this:

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

2 Comments

In the last line, you don't mean new AspectType()?
@Tazik_S yes, you are right. I just update it.
14

class expression can be used for simplicity.

 // 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);

1 Comment

Just a warning, in Node this is subject to module loading order. So be careful with using this. If you switch the names of these files around the example wouldn't work.
11

Several of the other answers come close, but honestly, I think you're better off going with the cleanest, simplest syntax. The OP requested a means of exporting a class in ES6 / ES2015. I don't think you can get much cleaner than this:

'use strict';

export default class ClassName {
  constructor () {
  }
}

3 Comments

Wrong. Reason: If you are using ES6 in Node 4, you cannot use ES6 module syntax without a transpiler, but CommonJS modules (Node's standard modules) work the same. (as per above)
Who the heck is still using Node 4? I think this is a valid answer for 99% of people.
It’s literally in the title of the question.
0

I had the same problem. What i found was i called my recieving object the same name as the class name. example:

const AspectType = new AspectType();

this screwed things up that way... hope this helps

Comments

0

Sometimes I need to declare multiple classes in one file, or I want to export base classes and keep their names exported because of my JetBrains editor understands that better. I just use

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

And somewhere else:

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

5 Comments

This is a bad way to do this... it will result in a collision some day.
Yeah well. No problem with collisions in owned projects. And if you purely import classes through require / module.exports, you're just shifting the problem to the module-names.
Stop trying to write PHP in JavaScript :P Jokes aside - as everyone else has said, this is just setting yourself up for problems later down the line. Globals are a very bad no good very very bad idea.
They are for people not being able to track their own code. Don't forget the filenames used in require are also globals. The no-globals dogma has its limits too.
Well, @TimHobbs, the things kids say.. Stuff like "They just are, period." That is exactly the kind of arguments you hear from people in lack of real arguments. You know. Even NodeJs uses globals. There is not even a problem when you have a well defined framework with well documented globals. Nice to hear that after all this years of study, cum laude graduation and feeding myself and my family for 20 years now, it's just "what I want to do anyway". Give me an argument or stop acting like a kid.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.