[javascript] ES6 export default with multiple functions referring to each other

in es6 there you can define a module of functions like this

export default {
    foo() { console.log('foo') }, 
    bar() { console.log('bar') },
    baz() { foo(); bar() }
}

the above seems to be valid code, but if I call baz() it throws an error:

ReferenceError: foo is not defined

How do you call foo from another function? in this case baz

Edit

Here's the code that actually doesn't work. I have simplified the code so it's only the core as needed

const tokenManager =  {
  revokeToken(headers) { 
    ... 
  },
  expireToken(headers) {
    ...
  },
  verifyToken(req, res, next) {
    jwt.verify(... => {
      if (err) {
        expireToken(req.headers)
      }
    })
  }
}

export default tokenManager 

and the error is

expireToken(req.headers);
        ^
ReferenceError: expireToken is not defined

Edit 2

I just tried adding tokenManager before expireToken and it finally works

This question is related to javascript ecmascript-6

The answer is


tl;dr: baz() { this.foo(); this.bar() }

In ES2015 this construct:

var obj = {
    foo() { console.log('foo') }
}

is equal to this ES5 code:

var obj = {
    foo : function foo() { console.log('foo') }
}

exports.default = {} is like creating an object, your default export translates to ES5 code like this:

exports['default'] = {
    foo: function foo() {
        console.log('foo');
    },
    bar: function bar() {
        console.log('bar');
    },
    baz: function baz() {
        foo();bar();
    }
};

now it's kind of obvious (I hope) that baz tries to call foo and bar defined somewhere in the outer scope, which are undefined. But this.foo and this.bar will resolve to the keys defined in exports['default'] object. So the default export referencing its own methods shold look like this:

export default {
    foo() { console.log('foo') }, 
    bar() { console.log('bar') },
    baz() { this.foo(); this.bar() }
}

See babel repl transpiled code.


One alternative is to change up your module. Generally if you are exporting an object with a bunch of functions on it, it's easier to export a bunch of named functions, e.g.

export function foo() { console.log('foo') }, 
export function bar() { console.log('bar') },
export function baz() { foo(); bar() }

In this case you are export all of the functions with names, so you could do

import * as fns from './foo';

to get an object with properties for each function instead of the import you'd use for your first example:

import fns from './foo';