Call a "local" function within module.exports from another function in module.exports?

node.jsExpress

node.js Problem Overview


How do you call a function from within another function in a module.exports declaration?

app.js
var bla = require('./bla.js');
console.log(bla.bar());
bla.js
module.exports = {
  
  foo: function (req, res, next) {
    return ('foo');
  },
  
  bar: function(req, res, next) {
    this.foo();
  }
 
}

I'm trying to access the function foo from within the function bar, and I'm getting:

> TypeError: Object # has no method 'foo'

If I change this.foo() to just foo() I get:

> ReferenceError: foo is not defined

node.js Solutions


Solution 1 - node.js

Change this.foo() to module.exports.foo()

Solution 2 - node.js

You could declare your functions outside of the module.exports block.

var foo = function (req, res, next) {
  return ('foo');
}

var bar = function (req, res, next) {
  return foo();
}

Then:

module.exports = {
  foo: foo,
  bar: bar
}

Solution 3 - node.js

You can also do this to make it more concise and readable. This is what I've seen done in several of the well written open sourced modules:

var self = module.exports = {

  foo: function (req, res, next) {
    return ('foo');
  },

  bar: function(req, res, next) {
    self.foo();
  }

}

Solution 4 - node.js

You can also save a reference to module's global scope outside the (module.)exports.somemodule definition:

var _this = this;

exports.somefunction = function() {
   console.log('hello');
}

exports.someotherfunction = function() {
   _this.somefunction();
}

Solution 5 - node.js

Another option, and closer to the original style of the OP, is to put the object you want to export into a variable and reference that variable to make calls to other methods in the object. You can then export that variable and you're good to go.

var self = {
  foo: function (req, res, next) {
    return ('foo');
  },
  bar: function (req, res, next) {
    return self.foo();
  }
};
module.exports = self;

Solution 6 - node.js

const Service = {
  foo: (a, b) => a + b,
  bar: (a, b) => Service.foo(a, b) * b
}

module.exports = Service

Solution 7 - node.js

Starting with Node.js version 13 you can take advantage of ES6 Modules.

export function foo() {
    return 'foo';
}

export function bar() {
    return foo();
}

Following the Class approach:

class MyClass {

    foo() {
        return 'foo';
    }

    bar() {
        return this.foo();
    }
}

module.exports = new MyClass();

This will instantiate the class only once, due to Node's module caching:
https://nodejs.org/api/modules.html#modules_caching

Solution 8 - node.js

To fix your issue, i have made few changes in bla.js and it is working,

var foo= function (req, res, next) {
  console.log('inside foo');
  return ("foo");
}

var  bar= function(req, res, next) {
  this.foo();
}
module.exports = {bar,foo};

and no modification in app.js

var bla = require('./bla.js');
console.log(bla.bar());

Solution 9 - node.js

What I do is to create a standalone foo function and reference it in both places.

That way, it prevents any issue with this irrespective of using an arrow or regular function

function foo(req,res,next) {
  return ('foo');
}

Then I can reference foo at both places

module.exports = {

  foo, // ES6 for foo:foo

  bar: function(req, res, next) {
    foo();
  }

}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionk00kView Question on Stackoverflow
Solution 1 - node.jsk00kView Answer on Stackoverflow
Solution 2 - node.jsBrettView Answer on Stackoverflow
Solution 3 - node.jsCalvin AlvinView Answer on Stackoverflow
Solution 4 - node.jsVilleView Answer on Stackoverflow
Solution 5 - node.jsgoozboxView Answer on Stackoverflow
Solution 6 - node.jsdavid_adlerView Answer on Stackoverflow
Solution 7 - node.jsm.spyratosView Answer on Stackoverflow
Solution 8 - node.jsAkash JainView Answer on Stackoverflow
Solution 9 - node.jsAbdullah OladipoView Answer on Stackoverflow