2008-08-16 9 views
13

me he encontrado con frecuencia los sitios que ponen toda su javascript dentro de una estructura de "espacio de nombres" en la línea de¿Existe una forma "concisa" de hacer espacios de nombres en JavaScript?

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

Pero establecer esto de forma segura con respecto a otros marcos de espacios de nombres parece requerir una cantidad relativamente fuerte de código (definido como> 2 líneas). Me preguntaba si alguien sabe de una forma concisa de hacer esto. y si hay una forma relativamente estándar/consistente para estructurarlo? p.ej. ¿El espacio de nombres "com" está directamente conectado al objeto global, o está conectado a través de un objeto de espacio de nombres?

[Editar: Vaya, obviamente {com = { ... } } no lograría nada cerca de lo que pretendía, gracias a Shog9 por señalarlo. : D]

Respuesta

19

JavaScript no tiene espacios de nombres independientes. Tiene funciones que pueden proporcionar el alcance para resolver nombres y objetos, que pueden contribuir a los datos nombrados accesibles en un ámbito determinado.

Ésta es tu ejemplo, corregido:

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

Ésta es una variable namespaces ser asignado un objeto literal. El objeto contiene una propiedad: com, un objeto con una propiedad: example, un objeto que presumiblemente contendría algo interesante.

Por lo tanto, puede escribir algo como namespaces.com.example. somePropertyOrFunctionOnExample y todo funcionará. Por supuesto, también es ridículo. No tiene un espacio de nombre jerárquico, tiene un objeto que contiene un objeto que contiene un objeto con las cosas que realmente le interesan.

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

Eso funciona igual de bien, sin la jerarquía inútil.

Ahora, si realmente quiere para construir una jerarquía, puede intentar algo como esto:

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() { /* ... */ } 
     }; 
    })(); 

... que es, en mi humilde opinión, razonablemente concisa.

+1

Aunque, ahora 'com_example' va a ser parte del objeto global. Supongamos que agregamos muchos más objetos 'com_something_else',' com_etc', y seguimos contaminando el nivel raíz del objeto global. ¿No sería preferible si tuviéramos solo un objeto 'com' en global donde todos los demás objetos fueran agregados? Además, no queremos sobrescribir ningún objeto existente, ¿qué sucede si se utilizan varias bibliotecas? – Peter

+2

@ Peter: si hay varias bibliotecas que definen los mismos símbolos, tendrás problemas sin importar nada; es por eso que las bibliotecas como jQuery llegan a tales extremos para meter todo en un solo objeto global. Mi punto no era que * debías * usar múltiples objetos de nivel superior, simplemente que fingir espacios de nombres con objetos profundamente anidados realmente no te compra nada en lugar de nombres de objetos locos. Vea mi último ejemplo para un método más práctico: use un solo nombre global que probablemente no colisione, y luego una técnica que permita que pedazos dispares de código le agreguen objetos. – Shog9

3

La biblioteca YUI library tiene un código que maneja el espacio de nombres usando una función que puede encontrar preferible. Otras bibliotecas pueden hacer esto también.

12

He aquí un interesante artículo de Peter Michaux en Javascript Namespacing. El autor analiza 3 tipos diferentes de espacios de nombre del Javascript:

  1. Prefijo namespacing
  2. individual namespacing
  3. objeto anidado namespacing

no voy a plagiar lo que dijo aquí, pero creo que su artículo es objeto muy informativo.

Peter incluso llegó al punto de señalar que hay consideraciones de rendimiento con algunos de ellos.Creo que sería interesante hablar sobre este tema al considerar que los nuevos planes ECMAScript Harmony han dejado de lado los planes 4.0 para el espaciado y el empaquetado de nombres.

6

Intento seguir la convención de Yahoo de incluir un objeto monoparental en el alcance global para contener todo;

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

Como alternativa a un punto o un guión bajo, se puede utilizar el carácter de signo de dólar:

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

¿Qué beneficio proporciona esto? – eyelidlessness

+0

Al hacerlo de esta manera, no tiene que definir sus espacios de nombres como un objeto con objetos internos anidados. Puedes simplemente definir el nombre en cualquier lugar. –

+0

Todavía no veo el beneficio de usar el signo $ en lugar de un punto o guión bajo. Creo que el signo $ hace que la palabra sea más difícil de leer que un punto o un guión bajo. –

5

para asegurarse de que no sobrescribir un objeto existente, debería hacerlo así que algo como:

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

o

var NameSpace = window.NameSpace || {}; 

De esta manera puede poner esto en la parte superior de cada archivo en su aplicación/sitio web sin preocuparse por sobrescribir el objeto de espacio de nombres. Además, esto le permitirá escribir pruebas unitarias para cada archivo individualmente.

1

me gusta también este (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

utilizar un objeto literal y, o bien el objeto this o el nombre explícito para hacerlo namespacing basa en las propiedades de hermanos de la variable local que contiene la función.Por ejemplo:

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 sin la explícita name propiedad:

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 sin el uso de 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);

Uso los RegExp o Object funciones constructoras para agregar propiedades de nombre para contrarrestar las variables y otros nombres comunes, a continuación, utilizar una prueba hasOwnProperty hacer la comprobación:

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; 
 
    }

DOM usa la siguiente convención para el espacio de nombres HTML y definiciones de interfaz SVG Elemento:

  • HTMLTitleElement
  • SVGTitleElement
  • SVGScriptElement
  • HTMLScriptElement

JavaScript núcleo utiliza prototipos para espacio de nombres del método toString como una forma simple de polimorfismo.

Referencias

Cuestiones relacionadas