2015-05-19 23 views
6

In ES5, ho potuto verificare l'esistenza di una "classe" (funzione di costruzione) sull'oggetto finestra:Classi ES6: che dire di instrospection?

if (window.MyClass) { 
... // do something 
} 

In ES6, according to this article, le classi a livello globale dichiarati sono globali, ma non le proprietà dell'oggetto globale (window, sui browser):

Ma ora ci sono anche variabili globali che non sono proprietà dell'oggetto globale. In ambito globale, le seguenti dichiarazioni creano tali variabili:

  • let dichiarazioni
  • const dichiarazioni
  • dichiarazioni di classe

Quindi, se non posso usare if (window.MyClass), c'è un modo fare lo stesso?

In realtà esiste un modo corretto per farlo senza utilizzare l'oggetto finestra?

+4

"significa che non sono accessibili sull'ambito globale della finestra" ... Che cosa ha a che fare l'hoisting con l'ambito globale? – elclanrs

+0

Grazie per le vostre risposte. Infatti, mi dispiace per la confusione, niente da vedere con il sollevamento. Ad ogni modo, avresti qualche raccomandazione per verificare l'esistenza della classe? forse i moduli es6? – Sam

+0

Controllare se il modulo root che dichiara la classe è dichiarato? –

risposta

6

In ES5, potremmo wheck l'esistenza di una classe per l'oggetto finestra

Solo se la funzione di costruzione è stato un globale, che è una pratica povero.

In ES6, according to this article, classi globalmente dichiarati sono globali, ma non proprietà dell'oggetto globale ...

corretto. (Lo stesso vale let e const dichiarazioni in ambito globale.) Viene definita in §8.1.1.4: Global Environment Records:

Record globale dell'ambiente è logicamente un singolo record ma è specificato come un composito incapsulare un ambiente Record oggetto e Record ambientale dichiarativo. L'oggetto Record Ambiente ha come oggetto base l'oggetto globale del Reame associato. Questo oggetto globale è il valore restituito dal metodo concreto GetThisBinding del record ambientale globale. (Ad esempio, l'oggetto globale a cui fa riferimento window sui browser   — TJ)L'oggetto componente Ambiente record di un record mondiale per l'ambiente contiene le associazioni per tutti i built-in globals (clausola 18) e tutte le associazioni introdotte da un FunctionDeclaration , GeneratorDeclaration o VariableStatement contenute nel codice globale. I binding per tutte le altre dichiarazioni ECMAScript nel codice globale sono contenuti nel componente dichiarativo Record dell'ambiente del record ambientale globale.

(corsivo mio) Così le cose che utilizzate per andare sul oggetto globale in ES5 e prima ancora fare (più generatori, perché sarebbe stato ancora più confusa se non lo facessero), ma il nuovo cose (let, const e class dichiarazioni) non. Sono globali, ma non proprietà dell'oggetto globale.

Torna alla tua domanda ...

Quindi, se non posso usare if (window.MyClass), c'è un modo per fare lo stesso?

Si potrebbe utilizzare

if (typeof MyClass === "function") { 

... dal typeof su un simbolo irrisolvibile non gettare un ReferenceError. Questo ha anche il vantaggio di verificare se MyClass è incluso nell'ambito del codice, anche se è non globale.

C'è c'è un Gotcha però: Se questo codice è nello stesso ambito in cui MyClass è dichiarato tramite class (o let o const) ma è sopraMyClass in tale ambito, anche il controllo typeof sarà gettare un ReferenceError, perché non è possibile accedere alla rilegatura crea a tutti (nemmeno con typeof) prima dello class (o let o const).

Ad esempio, questo genererà:

if (typeof MyClass === "function") { // ReferenceError here 
    // Yup, it's defined 
    // ... 
} 
// ... 
class MyClass { 
} 

Lo spazio dall'inizio del campo di applicazione al class, let, o const linea si chiama il temporale zona morta (TDZ) e non è possibile accedere al binding variabile a tutti. Di conseguenza, si deve prendere la ReferenceError:

let exists = false; 
try { 
    exists = typeof MyClass === "function"; 
} catch (e) { 
} 

In realtà c'è un modo corretto di fare questo senza usare oggetto finestra?

Fino moduli JavaScript fanno per un ampio sostegno del browser, ci sono un paio di modi:

  1. Utilizzare una libreria Definizione asincrono modulo di qualche tipo per gestire il caricamento dei moduli. Alcuni esempi: RequireJS, SystemJS, CommonJS

  2. Avere una singola variabile globale che verrà utilizzata per fare riferimento a un oggetto e rendere le varie proprietà globali dell'applicazione di tale oggetto.Ecco un tipico modo per farlo:

    var MyApp = MyApp || {}; 
    if (!MyApp.ThisModule) {     // You can leave this `if` out 
                  // if there's no chance of the file 
                  // being loaded more than once 
        MyApp.ThisModule = function(module) { 
         module.MyClass = class MyClass { 
          // ...class definition here... 
         } 
        }({}); 
    } 
    

Questo ti dà anche un ambito a portata di mano (la funzione anonima) in cui inserire eventuali globali a livello di modulo.

Problemi correlati