ES6导出默认,具有相互引用的多个功能

时间:2015-10-16 20:14:26

标签: javascript ecmascript-6

在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

我刚尝试在tokenManager之前添加expireToken,它最终有效

3 个答案:

答案 0 :(得分:94)

export default {...}构造只是这样的捷径:

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

export default funcs

现在必须明白,模块范围内没有foobarbaz功能。但是有一个名为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对象,而不必明确声明as @pawel has pointed out

另一个选项(以及我通常喜欢的选项)是在模块范围内声明这些函数。这允许直接引用它们:

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'即可在一个对象中获取所有已命名的导出。

答案 1 :(得分:18)

另一种方法是更改​​模块。通常,如果要导出一个带有大量函数的对象,则导出一堆命名函数会更容易,例如。

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

答案 2 :(得分:8)

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

请参阅babel repl transpiled code