2008-08-16 2 views
13

Ho spesso i siti che mettono tutta la loro javascript all'interno di una struttura "namespace" sulla falsariga diEsiste un modo "conciso" per fare il namespacing in JavaScript?

namespaces = { com : { example: { example.com's data} } 

Ma come impostare questa funzione in modo sicuro rispetto ad altri framework namespace sembra richiedere una quantità relativamente pesante di incontrato codice (definito come> 2 righe). Mi stavo chiedendo se qualcuno sa di un modo conciso per fare questo? e se esiste un modo relativamente standard/coerente di strutturarlo? per esempio. è lo spazio dei nomi "com" direttamente collegato all'oggetto globale o è collegato tramite un oggetto dello spazio dei nomi?

[Modifica: whoops, ovviamente {com = { ... } } non porterebbe a termine nulla di ciò che intendevo, grazie a Shog9 per averlo indicato. : D]

risposta

19

Javascript non dispone di spazi dei nomi autonomi. Ha funzioni, che possono fornire la possibilità di risolvere nomi e oggetti, che possono contribuire ai dati nominati accessibili in un determinato ambito.

Ecco il tuo esempio, corretto:

var namespaces = { com: { example: { /* example.com's data */ } } } 

Questa è una variabile namespaces essere stato assegnato un oggetto letterale. L'oggetto contiene una proprietà: com, un oggetto con una proprietà: example, un oggetto che presumibilmente contiene qualcosa di interessante.

Quindi, è possibile digitare qualcosa come namespaces.com.esempio. somePropertyOrFunctionOnExample e funzionerà tutto. Certo, è anche ridicolo. Non hai uno spazio dei nomi gerarchico, hai un oggetto contenente un oggetto contenente un oggetto con le cose che ti interessano veramente.

var com_example_data = { /* example.com's data */ }; 

Che funziona altrettanto bene, senza la gerarchia inutile.

Ora, se effettivamente vuole per costruire una gerarchia, si può provare qualcosa di simile:

com_example = com_example || {}; 
com_example.flags = com_example.flags || { active: false, restricted: true}; 

com_example.ops = com_example.ops || (function() 
    { 
     var launchCodes = "38925491753824"; // hidden/private 
     return { 
     activate: function() { /* ... */ }, 
     destroyTheWorld: function() { /* ... */ } 
     }; 
    })(); 

... che è, secondo me, abbastanza conciso.

+1

Anche se, ora 'com_example' sta per essere parte dell'oggetto globale. Supponiamo di aggiungere molti più oggetti 'com_something_else',' com_etc', quindi stiamo ancora inquinando il livello di root dell'oggetto globale. Non sarebbe preferibile se avessimo un solo oggetto 'com' nel globale in cui sono stati aggiunti tutti gli altri oggetti? Inoltre, non vogliamo sovrascrivere alcun oggetto esistente, cosa succede se vengono utilizzate più librerie. – Peter

+2

@Peter: se più librerie definiscono gli stessi simboli, avrai problemi, non importa cosa; è per questo che le librerie come jQuery fanno di tutto per inserire tutto in un unico oggetto globale. Il mio punto non era che dovresti * usare più oggetti di primo livello, ma solo che gli spazi dei nomi fasulli con oggetti profondamente nidificati non ti fanno davvero guadagnare nulla su nomi di oggetti pazzeschi. Guarda il mio ultimo esempio per un metodo più pratico: usa un singolo nome globale che è improbabile che possa scontrarsi, e quindi una tecnica che consente a diversi bit di codice di aggiungere oggetti ad esso. – Shog9

3

La libreria YUI library dispone di codice che gestisce il namespacing utilizzando una funzione che potrebbe essere preferibile. Altre biblioteche possono farlo anche

12

Ecco un interessante articolo di Peter Michaux su Javascript Namespacing. Si discute 3 diversi tipi di Javascript namespacing:

  1. prefisso namespacing
  2. singolo oggetto namespacing
  3. oggetto nidificato namespacing

Non voglio plagiare quello che ha detto qui, ma penso che il suo articolo è molto informativo.

Peter si è persino spinto a sottolineare che ci sono considerazioni sulle prestazioni con alcune di esse.Penso che questo argomento sarebbe interessante se si considera che i nuovi piani di ECMAScript Harmony hanno abbandonato i piani 4.0 per il namespacing e il packaging.

6

Provo a seguire la convenzione di Yahoo di rendere un singolo oggetto padre fuori dall'ambito globale per contenere tutto;

var FP = {}; 
FP.module = {}; 
FP.module.property = 'foo'; 
1

In alternativa a un punto o un trattino basso, è possibile utilizzare il simbolo del dollaro:

var namespaces$com$example = "data"; 
+0

Quali vantaggi offre? – eyelidlessness

+0

In questo modo, non è necessario definire gli spazi dei nomi come oggetti con oggetti interni nidificati. Puoi semplicemente definire il nome ovunque. –

+0

Non vedo ancora il vantaggio di utilizzare il segno $ invece di un punto o carattere di sottolineatura. Penso che il segno $ renda la parola più difficile da leggere di un punto o di un trattino basso. –

5

Per assicurarsi di non sovrascrivere un oggetto esistente, si dovrebbe quindi qualcosa di simile:

if(!window.NameSpace) { 
    NameSpace = {}; 
} 

o

var NameSpace = window.NameSpace || {}; 

In questo modo è possibile posizionarlo nella parte superiore di ogni file nella propria applicazione/sito Web senza doversi preoccupare della sovrascrittura dell'oggetto spazio dei nomi. Inoltre, questo ti consentirebbe di scrivere test unitari per ogni singolo file.

1

mi piace anche questo (source):

(function() { 
    var a = 'Invisible outside of anonymous function'; 
    function invisibleOutside() { 
    } 

    function visibleOutside() { 
    } 
    window.visibleOutside = visibleOutside; 

    var html = '--INSIDE Anonymous--'; 
    html += '<br/> typeof invisibleOutside: ' + typeof invisibleOutside; 
    html += '<br/> typeof visibleOutside: ' + typeof visibleOutside; 
    contentDiv.innerHTML = html + '<br/><br/>'; 
})(); 

var html = '--OUTSIDE Anonymous--'; 
html += '<br/> typeof invisibleOutside: ' + typeof invisibleOutside; 
html += '<br/> typeof visibleOutside: ' + typeof visibleOutside; 
contentDiv.innerHTML += html + '<br/>';​ 
0

utilizzare un oggetto letterale e sia l'oggetto this o il nome esplicito di fare namespacing basati sulle proprietà di pari livello della variabile locale che contiene la funzione.Per esempio:

var foo = { bar: function(){return this.name; }, name: "rodimus" } 
 
var baz = { bar: function(){return this.name; }, name: "optimus" } 
 

 
console.log(foo.bar()); 
 
console.log(baz.bar());

o senza l'esplicito name proprietà:

var foo = { bar: function rodimus(){return this; } } 
 
var baz = { bar: function optimus(){return this; } } 
 

 
console.log(foo.bar.name); 
 
console.log(baz.bar.name);

O senza utilizzare this:

var foo = { bar: function rodimus(){return rodimus; } } 
 
var baz = { bar: function optimus(){return optimus; } } 
 

 
console.log(foo.bar.name); 
 
console.log(baz.bar.name);

Utilizzare i RegExp o Object funzioni di costruzione per aggiungere proprietà del nome di contrastare variabili e altri nomi comuni, quindi utilizzare un test hasOwnProperty per un controllo:

var foo = RegExp(/bar/); 
 
    
 
/* Add property */ 
 
foo.name = "alpha"; 
 

 
document.body.innerHTML = String("<pre>" + ["name", "value", "namespace"] + "</pre>").replace(/,/g, "&#09;"); 
 

 
/* Check type */ 
 
if (foo.hasOwnProperty("name")) 
 
    { 
 
    document.body.innerHTML += String("<pre>" + ["foo", String(foo.exec(foo)), foo.name] + "</pre>").replace(/,/g, "&#09;"); 
 
    } 
 

 
/* Fallback to atomic value */ 
 
else 
 
    { 
 
    foo = "baz"; 
 
    } 
 

 
var counter = Object(1); 
 

 
/* Add property */ 
 
counter.name = "beta"; 
 

 
if (counter.hasOwnProperty("name")) 
 
    { 
 
    document.body.innerHTML += String("<pre>" + ["counter", Number(counter), counter.name] + "</pre>").replace(/,/g, "&#09;"); 
 
    } 
 
else 
 
    { 
 
    /* Fallback to atomic value */ 
 
    counter = 0; 
 
    }

Il DOM utilizza la seguente convenzione per lo spazio dei nomi HTML e definizioni dell'interfaccia SVG Elemento:

  • HTMLTitleElement
  • SVGTitleElement
  • SVGScriptElement
  • HTMLScriptElement

nucleo JavaScript utilizza prototipi namespace metodo toString come una semplice forma di polimorfismo.

Riferimenti