1

I have this Node.js module structure:

class Foo {

  log() {
    console.log(this.bar); // should log 'hello'
  }
}

module.exports = new Foo;

How can I 'require' the above and pass 'bar' as argument?

E.g something along these lines:

var Foo = require("./foo.js")("hello");

I'm specifically interested in how to do this with Class-based modules.


Update: Class-based Singletons are a Bad Idea™. I've switched to the object-literal module structure instead.

3
  • 2
    Never export class instances. Either use object literals (for singletons), or export the class itself. Commented Apr 2, 2016 at 8:04
  • 1
    Removing the parenthesis doesn't change anything, it's the new that you need to avoid! Commented Apr 2, 2016 at 10:58
  • 'new' or 'literal' are the same, they all instantiate an object and set the members and values, no need to be afraid of new, so you can do one of these: let foo = new Object({ name: "fooInstance", type: "someObject" }); or: let foo = { name: "fooInstance", type: "someObject" }; or let foo = new Foo("fooInstance", "someObject"); and it will all be the same all will return true to: foo instanceof Object (beside obviously the last example all others will return false on foo instanceof Foo) and they all execute the Object constructor, and return a reference to that created instance Commented Nov 27, 2021 at 13:47

3 Answers 3

2

You're mixing class and module definitions. You don't export an instance. You export a definition which you instantiate after you import it. Then you have to call a function

If you're using the ECMA2015 classes, then you can just write:

export default class Foo {
  constructor(bar) {
    this._bar = bar; 
  }

  log() {
    console.log(this._bar);
  }
}

Then your calling code should look like this:

import Foo from './foo.js';
let foo = new Foo('Boom!'); 
foo.log();

The import keyword is used like require in ES5.

Sign up to request clarification or add additional context in comments.

7 Comments

I'm quite sure I'm not mixing them up - requiring the way i posed it in my question will also instantiate the imported definition. The problem is that I can't pass arguments directly from the require statement to the constructor. There are many ways to do what I want but I specifically want to do just that - instantiate with arguments using a single-lined require
Yes, but you have to instantiate it with the argument. You can't call new in the export and then try to pass a constructor argument in your variable declaration.
No I don't. The code I posted instantiates itself (for lack of a better expression), on require, as a singleton. There is no need to re-instantiate it using new. It's exported as an instance already. I think the way I'm doing things doesn't allow to do what I want so I've switched to a different pattern. Thanks anyway
@NicholasKyriakides: If you want a singleton, you should not use a class.
@Bergi and that's what I did. I've marked @Gothdo answer as correct since it's the only one that instantiates in a single-lined require. Looks like it's a horrible anti-pattern but it answers the question in the best way.
|
0

You can change your foo.js to export the class, not an instance of it, and add a constructor which would assign the first argument to this.bar:

class Foo {
  constructor(bar) {
    this.bar = bar;
  }

  log() {
    console.log(this.bar); // should log 'hello'
  }
}

module.exports = Foo;

Then you can use it like that:

var foo = new (require("./foo.js"))("hello");
foo.log();

1 Comment

doesn't answers the OP question, just show how to export a class, and not the instance (see my comment to @ant: stackoverflow.com/a/36371526/530884)
0

Method 1:

create a module that will have only one instance from the class it contains on all modules,

lets call it level-driver.js:

const level = require('level-party'); // used for local lightweight db (google's leveldb) with multi process connection

class LevelDriver
{
    constructor(dbPath)
    {
        // connect to the local leveldb using json schema
        this.db = level(dbPath);
    }
    
    ...
}

// singleton instance holder
let instance = null;

function levelDriver(dbPath)
{
    if(instance == null)
    {
        // create an instance of LevelDriver
        instance = new LevelDriver(dbPath);
    }
    return instance;
}

// export only the instance (not the object) so it will be a singleton
// to all requireing modules (no matter the name or path)
module.exports = levelDriver;

then use it like this:

const levelDriver = require('./level-driver')('./users/users-db'); // manages leveldb connection and actions

Method 2:

const level = require('level-party'); // used for local lightweight db (google's leveldb) with multi process connection

class LevelDriver
{ 
    constructor(dbPath)
    {
        // connect to the local leveldb using json schema
        this.db = level(dbPath);
    }

    ...
}

// export only the instance (not the object) so it will be a singleton
// to all requireing modules (no matter the name or path)
module.exports = (dbPath) => { return new LevelDriver(dbPath) }

then use it like this:

const levelDriver = require('./level-driver')('./users/users-db'); // manages leveldb connection and actions

Comments

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.