2015-09-23 18 views
7

Apparentemente, ES6 doesn't need namespacing perché ogni file è un modulo separato.Namespacing con IIFE in ES6?

Ma allora, come evitare l'interferenza globale nello spazio dei nomi?

Per esempio, Babel compila il mio file scripts/main.js semplicemente sostituendo const con var.

var alert = 'This line doesn\'t do anything.' 
 
window.alert(alert)

Un namespace (denominato ANS sotto) con un IIFE impedisce collisioni di nomi:

const ANS = (function() { 
 
    const alert = 'This works' 
 
    window.alert(alert + '.') 
 
    return {alert: alert + ' too.'} 
 
})() 
 
alert(ANS.alert)

Aggiunta proprietà allo spazio ANS è più pulita aggiunta loro al namespace globale, window o this. E l'IIFE fornisce ulteriori incapsulamenti.

Quindi, non è il secondo modo, ovvero la creazione di uno spazio dei nomi personalizzato con un IIFE, migliore del primo? Se è così, c'è un modo nuovo/più bello di farlo in ES2015? Perché Babel non fa questo per me?

+0

Perché sarebbe la sovrascrittura di un mondiale del genere essere qualcosa ti devi preoccupare? Si potrebbe anche fare 'alert()' comunque. – loganfsmyth

+0

@loganfsmyth perché la finestra [Oggetto globale] (http://www.ecma-international.org/ecma-262/6.0/#sec-global-object) 'ha molte proprietà. Anche la mia app ne avrà alcune e voglio evitare potenziali collisioni di nomi. Si prega di vedere la mia domanda aggiornata. – ma11hew28

+0

Forse c'è qualche errore di comunicazione su questa domanda. La tua preoccupazione nel primo esempio è 'alert === window.alert'? Se è così, questo non è il caso in un vero ambiente ES6, anche se potrebbe farlo con un transpiler. Non è assolutamente il caso quando si usano i moduli ES6 con un adeguato bundler di moduli. – loganfsmyth

risposta

2

Ma come evitare di sovrascrivere globalmente da un modulo?

Non è possibile. A questo riguardo, nulla è cambiato rispetto a ES5. Il consiglio è ancora: evitare l'uso di globals.

+0

Grazie. Allora, dovrei creare ancora uno spazio dei nomi con un IIFE? Vedi la mia domanda aggiornata. – ma11hew28

+0

IIFE sono principalmente utilizzati per creare scope. I moduli hanno già un proprio ambito, quindi non è necessario utilizzare un IIFE in un modulo (a meno che, ovviamente, non lo si voglia fare all'interno del modulo stesso). Il modo in cui organizzi o esporti i tuoi dati in/dal modulo dipende da te. –

9

Apparentemente, ES6 non richiede il namespacing perché ogni file è un modulo separato.

Non esattamente. Ogni modulo ha il suo ambito, è corretto, ma non tutti i file sono un modulo. Esistono ancora script in ES6 che funzionano proprio come quelli di ES5 e vengono eseguiti nell'ambito globale.
In quegli script, è ancora necessario evitare globalmente il più possibile, in genere non dichiarando/assegnando alcuna variabile o avvolgendo il "modulo" in un IEFE per assegnargli un ambito variabile separato.

C'è un modo nuovo/più bello di farlo in ES6?

È possibile utilizzare un blocco e dichiarazioni di variabili lessicali (let, const, function):

{ 
    const msg = 'This line doesn\'t do anything.' 
    window.alert(msg); 
} 
// msg is not defined here 

In alternativa è possibile utilizzare una funzione di freccia nel vostro IEFE, che consentono di utilizzare this per riferirsi a l'oggetto globale senza bisogno di use .call(this)):

(() => { 
    var msg = 'This line doesn\'t do anything.' 
    window.alert(msg); 
})(); 

Ma allora, come evitare l'interferenza globale nello spazio dei nomi o il nome delle collisioni?

Nei moduli ES6, non c'è nulla di globale tranne gli oggetti incorporati e forse l'oggetto globale. Evita di modificarli.

E ovviamente dovrai preoccuparti delle collisioni tra i nomi dei moduli: come farlo dovrebbe essere spiegato nei documenti per il meccanismo di risoluzione del tuo caricatore di moduli.

+0

È a mia conoscenza che gli script in ES6 hanno un ambiente lessicale condiviso, quindi mentre 'var alert = 'blah';' sarebbe equivalente a 'window.alert = 'blah';', 'let alert =' blah'' e' const alert = 'blah'; 'creerebbe una variabile globalmente con scope lessicale senza cambiare' window.alert'. Più difficile da traspare però. – loganfsmyth

+0

Voi ragazzi avete senso, ma [Babel] (https://babeljs.io) non avvolge il mio codice in un IIFE se uso 'const' o un blocco. – ma11hew28

+0

@MattDiPasquale: Apparentemente è perché Babel compila solo moduli, non script: [numero 1049] (https://github.com/babel/babel/issues/1049) – Bergi

1

Apparentemente, ES6 non richiede il namespaces perché ogni file è un modulo separato .

Questa è disinformazione. Per quanto ne so, solo i file che utilizzano export sono moduli ES6. Senza export, un file ES6 è solo uno script ordinario che ha accesso all'ambito globale a meno che non sia incluso in un IIFE o venga trasformato durante un processo di compilazione.

Revisione (12 luglio 2016): Apparentemente, ho corretto la disinformazione con maggiore disinformazione. Come Kyle Simpson clarifies below, "Secondo le specifiche attuali, ciò che rende un file un modulo ES6 è come l'ambiente (nodo, browser, ecc.) Sceglie di caricarlo, non il suo contenuto."

In You Do not Know JS: ES & Al di là, Kyle Simpson, alias @getify, afferma

"Moduli fanno ancora hanno accesso a finestra e tutti i "globali" che appendere fuori esso , non solo come ambito lessicale di alto livello, ma è davvero necessario che lo rimanga lontano dai globali nei moduli, se possibile. "

Ora alle vostre domande.

[I] sn't il secondo modo, vale a dire, la creazione di uno spazio dei nomi personalizzato con un IIFE, meglio del primo?

Dipende dall'ambiente in cui è in esecuzione il modulo. Ad esempio, in node, non esiste l'oggetto Window; pertanto, in quell'ambiente non è necessario preoccuparsi dei moduli che inquinano lo spazio dei nomi globale.

D'altra parte, nel browser, Window è un'API Web globale e il modulo può accedervi. Tecnicamente, tutto ciò che il tuo modulo si collega a Window non è, a rigor di termini, globale; tuttavia, tutto ciò che è collegato a Window è così vicino a un globale che in genere è considerato una cattiva pratica modificarlo tranne tramite Window.

[H] devo evitare l'interferenza globale nello spazio dei nomi?

e

[I] s là un/modo più nuovo più bello di fare questo in ES2015?

Non so quali sono le migliori pratiche per gestire l'ambito in ES6. Per il momento, faccio la seguente:

  • Se un file è un modulo, è ambito di primo livello è il file stesso, quindi non riguardano me stesso con portata globale.
  • Se un file non è un modulo, lo avvolgo in un IIFE.

Fonte: You Don't Know JS: ES & Beyond anche raccomandato: ES6 In Depth: Modules da Jason Orendorff

+2

Chiarimento: "solo i file che usano l'esportazione sono moduli ES6". Non esattamente. Secondo le specifiche attuali, ciò che rende un file un modulo ES6 è come l'ambiente (nodo, browser, ecc.) Sceglie di caricarlo, non il suo contenuto. –