2015-10-16 14 views
19

in ES6 non è possibile definire un modulo di funzioni come questoES6 di default di esportazione con molteplici funzioni che si riferiscono l'uno all'altro

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

quanto sopra sembra essere codice valido, ma se chiamo baz() che genera un errore:

ReferenceError: foo is not defined

Come si chiama foo da un'altra funzione? in questo caso baz

Modifica

Ecco il codice che in realtà non funziona. Ho semplificato il codice in modo che solo il nucleo come necessario

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

export default tokenManager 

e l'errore è

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

Edit 2

Ho provato ad aggiungere tokenManager prima expireToken e funziona infine

+1

Vedere la risposta di my o @ pawel. Per correggere, sostituire 'expireToken (req.headers)' con 'tokenManager.expireToken (req.headers)' o con 'this.expireToken (req.headers)'. – skozin

risposta

38

Il export default {...} costruzione è solo una scorciatoia per qualcosa di simile:

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

export default funcs 

Deve diventare evidente ora che non ci sono foo, bar o baz funzioni nel campo di applicazione del modulo. Ma c'è un oggetto chiamato funcs (anche se in realtà non ha nome) che contiene queste funzioni come proprietà e che diventerà l'esportazione predefinita del modulo.

Così, per risolvere il tuo codice, ri-scrivere senza usare la scorciatoia e si riferiscono a foo e bar come proprietà di funcs:

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

export default funcs 

Un'altra opzione è quella di utilizzare this parola chiave per fare riferimento a funcs oggetto senza dovendo dichiararlo esplicitamente, as @pawel has pointed out.

Un'altra opzione (e quella che generalmente preferisco) è dichiarare queste funzioni nell'ambito del modulo. Questo permette di fare riferimento a loro direttamente:

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

export default {foo, bar, baz} 

E se si vuole la comodità di esportazione di default e capacità di importare elementi singolarmente, è anche possibile esportare tutte le funzioni singolarmente:

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

Oppure, come suggerito da @loganfsmyth, puoi fare a meno dell'esportazione predefinita e usare semplicemente import * as util from './util' per ottenere tutte le esportazioni con nome in un oggetto.

+0

Ho provato questo, ma non riuscivo a farlo funzionare. Ho modificato la domanda con il codice reale. Riesci a vedere cosa va storto qui? – chrs

+0

@chrs, guarda il mio commento sotto la tua domanda. È necessario sostituire 'expireToken' con' tokenManager.expireToken'. – skozin

+0

Ti ho concesso l'accettazione poiché eri il primo a rispondere. Anche le altre risposte sono buone, ma visto che sei stato il primo che hai guadagnato :) – chrs

7

tl; dr: baz() { this.foo(); this.bar() }

In ES2015 questo costrutto:

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

è uguale a questo codice ES5:

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

exports.default = {} è come la creazione di un oggetto, l'esportazione di default traduce in codice ES5 in questo modo:

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

ora è abbastanza ovvio (spero) che baz prova a chiamare foo un d bar definiti da qualche parte nell'ambito esterno, che non sono definiti. Ma this.foo e this.bar verranno risolti nelle chiavi definite nell'oggetto exports['default']. Così l'esportazione di default riferimento i propri metodi shold simile a questa:

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

Vedi babel repl transpiled code.

+0

Grazie per la risposta! Sono andato con la soluzione di Sam però :) 1 su – chrs

13

Un'alternativa è cambiare il modulo. Generalmente, se esporti un oggetto con un sacco di funzioni su di esso, è più facile esportare un gruppo di funzioni con nome, ad es.

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

In questo caso si sta esportare tutte le funzioni con i nomi, in modo che si possa fare

import * as fns from './foo'; 

per ottenere un oggetto con le proprietà per ogni funzione, invece di importazione desideri utilizzare per la vostra primo esempio:

import fns from './foo'; 
+1

Questa è sicuramente la soluzione migliore. Usa le esportazioni nominate invece degli oggetti predefiniti. – Bergi

Problemi correlati