ES6导出默认有多个函数相互引用

ES6 export default with multiple functions referring to each other

本文关键字:函数 引用 默认 ES6      更新时间:2023-09-26

在es6中你可以定义一个函数模块,像这样

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

似乎是有效的代码,但如果我调用baz(),它抛出一个错误:

ReferenceError: foo is not defined

如何从另一个函数调用foo ?本例为baz

编辑

这是实际上不起作用的代码。我已经简化了代码,所以它只有核心需要

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

,错误是

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

编辑2

我只是试着在expireToken之前添加tokenManager,它最终工作

export default {...}结构只是这样的一个快捷方式:

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

现在必须变得明显,在模块的作用域中没有foo, barbaz函数。但是有一个名为funcs的对象(尽管实际上它没有名称),它包含这些函数作为其属性,并将成为模块的默认导出。

所以,要修复你的代码,重写它,不使用快捷方式,并引用foobar作为funcs的属性:

const funcs = {
    foo() { console.log('foo') }, 
    bar() { console.log('bar') },
    baz() { funcs.foo(); funcs.bar() } // here is the fix
}
export default funcs

另一个选择是使用this关键字来引用funcs对象,而不必显式声明它,正如@pawel所指出的。

另一种选择(也是我通常更喜欢的一种)是在模块作用域中声明这些函数。这允许直接引用它们:

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

如果你想要方便的默认导出能力单独导入项,你也可以单独导出所有的函数:

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

或者,正如@loganfsmyth建议的那样,您可以不使用默认导出,只使用import * as util from './util'在一个对象中获取所有命名的导出。

另一种选择是更改模块。一般来说,如果你要导出一个带有一堆函数的对象,导出一堆命名函数会更容易,例如

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

在本例中,您将导出所有带名称的函数,因此您可以执行

import * as fns from './foo';

为每个函数获取具有属性的对象,而不是您在第一个示例中使用的导入:

import fns from './foo';

br: baz() { this.foo(); this.bar() }

在ES2015中:

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

等于这个ES5代码:

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

exports.default = {}就像创建一个对象,你的默认导出转换为ES5代码,像这样:

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

现在很明显(我希望)baz试图调用在外部作用域中定义的foobar,这是未定义的。但是this.foothis.bar将解析为exports['default']对象中定义的键。所以默认的导出引用它自己的方法应该是这样的:

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