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

1

3 Answers

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.

4

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'; 
1

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.

1

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

You Might Also Like