Pergunta

Tenho encontrado frequentemente sites que colocam todo o seu JavaScript dentro de um namespace estrutura nos moldes de:

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

No entanto, configurar isso com segurança em relação a outras estruturas com namespace parece exigir uma quantidade relativamente grande de código (definida como> 2 linhas).Eu queria saber se alguém conhece uma maneira concisa de fazer isso?Além disso, existe uma maneira relativamente padrão/consistente de estruturá-lo?Por exemplo, é o com namespace diretamente anexado ao objeto global ou é anexado por meio de um objeto de namespace?

[Editar:opa, obviamente {com = { ... } } não conseguiria nada próximo do que pretendi, obrigado ao Shog9 por apontar isso.]

Foi útil?

Solução

Javascript não possui namespaces independentes.Possui funções, que podem fornecer escopo para resolução de nomes, e objetos, que podem contribuir para que os dados nomeados sejam acessíveis em um determinado escopo.

Aqui está o seu exemplo, corrigido:

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

Esta é uma variável namespaces sendo atribuído um objeto literal.O objeto contém uma propriedade: com, um objeto com uma propriedade: example, um objeto que provavelmente conteria algo interessante.

Então, você pode digitar algo como namespaces.com.exemplo.somePropertyOrFunctionOnExample e tudo vai funcionar.Claro, também é ridículo.Você não tem um namespace hierárquico, você tem um objeto contendo um objeto contendo um objeto com as coisas que realmente lhe interessam.

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

Isso funciona igualmente bem, sem a hierarquia inútil.

Agora, se você realmente querer para construir uma hierarquia, você pode tentar algo assim:

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

... o que é, IMHO, razoavelmente conciso.

Outras dicas

Aqui estava um artigo interessante de Peter Michaux sobre Namespace Javascript.Ele discute três tipos diferentes de namespace Javascript:

  1. Namespace de prefixo
  2. Namespace de objeto único
  3. Namespace de objetos aninhados

Não vou plagiar o que ele disse aqui, mas acho que seu artigo é muito informativo.

Peter chegou ao ponto de apontar que há considerações de desempenho em alguns deles.Acho que seria interessante falar sobre este tópico, considerando que os novos planos do ECMAScript Harmony abandonaram os planos 4.0 para namespace e empacotamento.

Tento seguir a convenção do Yahoo de criar um único objeto pai no escopo global para conter tudo;

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

Para ter certeza de não substituir um objeto existente, você deve fazer algo como:

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

ou

var NameSpace = window.NameSpace || {};

Dessa forma, você pode colocar isso no topo de cada arquivo em seu aplicativo/site sem se preocupar em sobrescrever o objeto namespace.Além disso, isso permitiria escrever testes de unidade para cada arquivo individualmente.

O Biblioteca YUI biblioteca possui código que lida com namespace usando uma função que você pode achar preferível.Outras bibliotecas também podem fazer isso.

Como alternativa a um ponto ou sublinhado, você pode usar o cifrão:

var namespaces$com$example = "data"; 

Eu também gosto disso (fonte):

(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/>';​

Use um objeto literal e o this objeto ou o nome explícito para fazer o namespace com base nas propriedades irmãs da variável local que contém a função.Por exemplo:

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

Ou sem o explícito name propriedade:

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

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

Ou sem usar 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);

Use o RegExp ou Object funções construtoras para adicionar propriedades de nome a variáveis ​​de contador e outros nomes comuns e, em seguida, use um hasOwnProperty teste para fazer a verificação:

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

O DOM usa a seguinte convenção para definir namespaces de interface de elementos HTML e SVG:

  • HTMLTitleElement
  • Elemento SVGTitle
  • Elemento SVGScript
  • Elemento HTMLScript

O núcleo do JavaScript usa protótipos para criar o namespace do toString método como uma forma simples de polimorfismo.

Referências

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top