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
Solution 1:
The export default {...}
construction is just a shortcut for something like this:
const funcs = {
foo() { console.log('foo') },
bar() { console.log('bar') },
baz() { foo(); bar() }
}
export default funcs
It must become obvious now that there are no foo
, bar
or baz
functions in the module's scope. But there is an object named funcs
(though in reality it has no name) that contains these functions as its properties and which will become the module's default export.
So, to fix your code, re-write it without using the shortcut and refer to foo
and bar
as properties of funcs
:
const funcs = {
foo() { console.log('foo') },
bar() { console.log('bar') },
baz() { funcs.foo(); funcs.bar() } // here is the fix
}
export default funcs
Another option is to use this
keyword to refer to funcs
object without having to declare it explicitly, as @pawel has pointed out.
Yet another option (and the one which I generally prefer) is to declare these functions in the module scope. This allows to refer to them directly:
function foo() { console.log('foo') }
function bar() { console.log('bar') }
function baz() { foo(); bar() }
export default {foo, bar, baz}
And if you want the convenience of default export and ability to import items individually, you can also export all functions individually:
// util.js
export function foo() { console.log('foo') }
export function bar() { console.log('bar') }
export function baz() { foo(); bar() }
export default {foo, bar, baz}
// a.js, using default export
import util from './util'
util.foo()
// b.js, using named exports
import {bar} from './util'
bar()
Or, as @loganfsmyth suggested, you can do without default export and just use import * as util from './util'
to get all named exports in one object.
Solution 2:
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';