2015-10-16 64 views
19

那里你可以定义的功能模块这样ES6出口默认具有多种功能的参照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

我只是想增加tokenManagerexpireToken之前最后和它的工作原理

+1

请参阅我的或@ pawel的答案。要修复,用'tokenManager.expireToken(req.headers)'或'this.expireToken(req.headers)'替换'expireToken(req.headers)'。 – skozin

回答

38

export default {...}建设仅仅是这样的一个快捷方式:

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

export default funcs 

现在必须变得明显,有在模块的范围没有foobarbaz功能。但有一个名为funcs的对象(虽然实际上它没有名字),它包含这些函数作为它的属性,并将成为模块的默认导出。

所以,要解决你的代码,它重新写不使用快捷方式,并参考foobarfuncs属性:

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

+0

我试过这个,但不能使它的工作。我用真实的代码编辑了这个问题。你能看到这里出了什么问题吗? – chrs

+0

@chrs,在你的问题下看到我的评论。你需要用'tokenManager.expireToken'替换'expireToken'。 – skozin

+0

因为你是第一个回答,所以我已经给你接受。其他答案也很好,但因为你是第一个获得它:) – chrs

7

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试图呼吁foo和d bar在外部范围的某个位置定义,它们是未定义的。但是this.foothis.bar将解析为在exports['default']对象中定义的键。所以默认出口引用其自己的方法shold是这样的:

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

babel repl transpiled code

+0

感谢您的回答!我去了山姆的解决方案虽然:) 1 – chrs

13

一种替代方法是改变你的模块。一般情况下,如果你要导出一个包含一堆函数的对象,那么导出一堆命名函数比较容易。

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

这绝对是最好的解决方案。使用命名导出而不是默认对象。 – Bergi