404

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

2
  • 6
    I tested your code and have no errors. The bar function returns undefined because have no return statement. Are you sure you are testing correctly? Commented Oct 2, 2014 at 19:25
  • 1
    Tested in node version v8.12.0 and does no longer throw the error. bar has no return statement so running console.log(bla.bar()) simply returns undefined Commented Apr 15, 2019 at 19:00

10 Answers 10

510

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

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

9 Comments

@NamNguyen Calling exports.foo() seems a little bit awkward and hard to read.
I think that this is better than the accepted answer. If you define functions outside of the exports scope, it adds an extra level of indirection, and while it can be desirable sometimes, it makes it more complicated, to refactor, e.g. rename the function, of find usage of the function, etc.
module.exports.foo() and exports.foo() do not work for me with Node.js v5.8.0.
exports.foo() is not working but module.exports.foo() is working with NodeJS v6.9.1
exports.foo only works if you define an exports varible that references the module.exports object const exports = module.exports = {} and then set functions foo and bar as its methods exports.foo = function() {} and exports.bar = function (){ exports.foo() } here to reference foo in the bar use exports.foo. If you want to reference foo from bar inside module.exports object then use module.exports.foo inside bar.
|
205

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
}

4 Comments

what if I wanted to access properties of the object from the method?
I'm getting TypeError: yourClass.youMethod is not a function when I did this. I'm using node version 6.9.1. Do you have to have a return statement? I do not have return statements since all my code is async in the functions.
Nice comparison of different styles -- gist.github.com/kimmobrunfeldt/10848413
Or, more concisely using ES6, module.exports = { foo, bar, }
133

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();
  }

}

4 Comments

Is this Node.js version specific? I am trying this with v5.8.0 and it is logging undefined.
@doublejosh Did... did you read the question? It's asking how you call one exported function from another. It has nothing to do with access restrictions.
Yes I read it, please re-read. This answer makes foo() exported with the module, which goes against the point of a "local" function only called within the module.
This works great. I actually need foo() exported to be used outside, but also need to call it within sibling function. Thank you!
68

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();
}

5 Comments

It's more cleaner solution!
no need for the _this and you can simply use this where you need it
used this directly, no need to declare _this
That suggestion is useful once this is no longer the right this. (Promises and callbacks)
I like this solution the best because it also gives an example of scoping in NodeJS modules.
43

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;

Comments

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

module.exports = Service

3 Comments

This is particularly usable because your code there is calling Service.foo(), and your client code will also be calling Service.foo() with the same naming.
This is a perfect answer!
I used it with Salesforce lwc and it works perfectly, I like this clean method
21

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

4 Comments

and how does one call a static method with this approach?
@CodeofGod Just call it as you would call any other static method. In this case, if foo was static you would call it from inside bar like this: MyClass.foo().
yeah i get that, but how would you call it from a controller that is importing it like... const oAccounts = require("...");
You can export the actual class, not an instance of the class. That way you can use its static methods. If you then need to use its instance methods though, then you will have to instantiate the class in your controller.
8

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

1 Comment

In the function bar, this.foo() doesn't work... it needs to be foo()
0

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();
  }

}

Comments

0

If you do like this, you will be losing your this object reference inside your calling function. For eg:

    module.exports.a = function () {
      return true
    }
    
    module.exports.b = function() {
      return this.a();
    }

here you will get the issue because when you call this.a(), it is referencing the this object of the b function.

To solve this your have to store your this object reference somewhere or use the arrow function, because the arrow function doesn't have there own this object so it will always reference the outer this object

To solve this, modify your function like this

    module.exports.a = function () {
      return true
    }
    
    module.exports.b = () => {
      return this.a();
    }

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.