Como crio um espaço para nome em JavaScript para que meus objetos e funções não sejam substituídos por outros objetos e funções com o mesmo nome? Eu usei o seguinte:
if (Foo == null || typeof(Foo) != "object") { var Foo = new Object();}
Existe uma maneira mais elegante ou sucinta de fazer isso?
javascript
namespaces
javascript-namespaces
Scott McKenzie
fonte
fonte
Respostas:
Eu gosto disso:
fonte
MyApp
, por exemplo, emMyApp.Views.Profile = {}
vez deMyApp.users = {}
eMyViews.Profile = {}
. Não necessariamente que deva haver apenas dois níveis de profundidade.Eu uso a abordagem encontrada no site Enterprise jQuery :
Aqui está o exemplo deles, mostrando como declarar propriedades e funções privadas e públicas. Tudo é feito como uma função anônima de execução automática.
Portanto, se você deseja acessar um dos membros públicos, basta ir
skillet.fry()
ouskillet.ingredients
.O mais legal é que agora você pode estender o espaço para nome usando exatamente a mesma sintaxe.
O terceiro
undefined
argumentofonte
undefined
argumento é a fonte da variável de valorundefined
. Ao trabalhar com navegadores mais antigos / padrão javascript (ecmascript 5, javascript <1.8.5 ~ firefox 4), a variável de escopo globalundefined
é gravável, para que qualquer pessoa possa reescrever seu valor. Adicionar um terceiro argumento adicional que você não está passando vale a penaundefined
, então você estava criando um espaço para nomeundefined
que não seria reescrito por fontes externas.window.skillet = window.skillet || {}
disso é que ele permite que vários scripts sejam adicionados com segurança ao mesmo espaço para nome quando eles não souberem antecipadamente em que ordem serão executados. Isso pode ser útil se você deseja reorganizar suas inclusões de script arbitrariamente sem quebrar seu código ou se deseja carregar scripts de forma assíncrona com o atributo async e, portanto, não tem garantia sobre a ordem de execução. Veja stackoverflow.com/questions/6439579/…Outra maneira de fazê-lo, que considero um pouco menos restritiva que a forma literal do objeto, é esta:
A descrição acima é muito parecida com o padrão do módulo e, quer você goste ou não , permite expor todas as suas funções como públicas, evitando a estrutura rígida de um literal de objeto.
fonte
ns().publicFunction()
, ou seja,ns.publicFunction()
funciona.new
palavra - chave na frente dafunction
palavra - chave. Basicamente, o que está fazendo é declarar uma função anônima (e, como uma função, também é um construtor) e, em seguida, chama-a imediatamente como um construtor usandonew
. Como tal, o valor final que é armazenado dentrons
é uma instância (exclusiva) desse construtor anônimo. Espero que faça sentido.Sim. Por exemplo:
então você pode ter
fonte
var your_namespace = your_namespace = your_namespace || {}
Normalmente, eu o construo em um fechamento:
Meu estilo ao longo dos anos teve uma mudança sutil desde que escrevi isso, e agora me pego escrevendo o fechamento assim:
Dessa maneira, acho a API pública e a implementação mais fáceis de entender. Pense na declaração de retorno como uma interface pública para a implementação.
fonte
MYNS.subns = MYNS.subns || {}
?var foo = function
efunction foo
são semelhantes, sendo privadas; devido à natureza de tipo dinâmico do JavaScript, o último é um pouco mais rápido, pois ignora algumas instruções nos pipelines da maioria dos intérpretes. Comvar foo
, o sistema de tipos precisa ser chamado para descobrir qual tipo está sendo atribuído ao referido var, enquanto, comfunction foo
, o sistema de tipos sabe automaticamente que é uma função, então algumas chamadas de função são ignoradas, o que se traduz em menos invocações de instruções da CPU, comojmp
,pushq
,popq
, etc, que se traduz em um oleoduto CPU mais curto.function foo
sintaxe é mais legível. E eu ainda gosto da minha versão.Como você pode gravar arquivos diferentes de JavaScript e, posteriormente, combiná-los ou não em um aplicativo, cada um precisa poder recuperar ou construir o objeto de espaço para nome sem danificar o trabalho de outros arquivos ...
Um arquivo pode pretender usar o espaço para nome
namespace.namespace1
:Outro arquivo pode querer usar o espaço para nome
namespace.namespace2
:Esses dois arquivos podem viver juntos ou separados sem colidir.
fonte
Veja como Stoyan Stefanov faz isso em seu livro JavaScript Patterns , que eu achei muito bom (também mostra como ele faz comentários que permitem a documentação da API gerada automaticamente e como adicionar um método ao protótipo de um objeto personalizado):
fonte
Eu uso essa abordagem:
O código externo pode ser:
fonte
ns = ns || {}
possa parecer mais defensivo, pode levar a outros resultados inesperados.Este é um acompanhamento do link do user106826 para Namespace.js. Parece que o projeto foi transferido para o GitHub . Agora é smith / namespacedotjs .
Eu tenho usado esse simples auxiliar de JavaScript no meu pequeno projeto e, até agora, parece ser leve e versátil o suficiente para lidar com namespacing e carregar módulos / classes. Seria ótimo se me permitisse importar um pacote para um espaço para nome de minha escolha, não apenas para o espaço para nome global ... suspiro, mas isso está além do ponto.
Ele permite que você declare o espaço para nome e defina objetos / módulos nesse espaço para nome:
Outra opção é declarar o espaço para nome e seu conteúdo de uma vez:
Para obter mais exemplos de uso, consulte o arquivo example.js na fonte .
fonte
Amostra:
Opcionalmente, você pode declarar uma
local
variável,same
curtirself
e atribuir,local.onTimeout
se desejar que ela seja privada.fonte
Você pode declarar uma função simples para fornecer espaços para nome.
fonte
Se você precisar do escopo privado:
caso contrário, se você nunca usará o escopo privado:
fonte
O padrão do módulo foi originalmente definido como uma maneira de fornecer encapsulamento público e privado para as classes na engenharia de software convencional.
Ao trabalhar com o padrão Módulo, podemos achar útil definir um modelo simples que usamos para começar a usá-lo. Aqui está um que abrange variáveis de espaçamento entre nomes, públicas e privadas.
Em JavaScript, o padrão Module é usado para emular ainda mais o conceito de classes de forma que possamos incluir métodos e variáveis públicos / privados em um único objeto, protegendo partes específicas do escopo global. O que isso resulta é uma redução na probabilidade de os nomes de nossas funções entrarem em conflito com outras funções definidas em scripts adicionais na página.
Vantagens
por que o padrão do módulo é uma boa escolha? Para iniciantes, é muito mais limpo para os desenvolvedores que têm um background orientado a objetos do que a idéia de encapsulamento verdadeiro, pelo menos da perspectiva do JavaScript.
Em segundo lugar, ele suporta dados privados - portanto, no padrão Módulo, partes públicas do nosso código são capazes de tocar as partes privadas; no entanto, o mundo exterior não consegue tocar nas partes privadas da classe.
Desvantagens
As desvantagens do padrão do módulo são que, como acessamos os membros públicos e privados de maneira diferente, quando desejamos alterar a visibilidade, na verdade temos que fazer alterações em cada local em que o membro foi usado.
Também não podemos acessar membros privados em métodos que são adicionados ao objeto posteriormente . Dito isto, em muitos casos, o padrão do módulo ainda é bastante útil e, quando usado corretamente, certamente tem o potencial de melhorar a estrutura do nosso aplicativo.
O padrão revelador do módulo
Agora que estamos um pouco mais familiarizados com o padrão do módulo, vamos dar uma olhada em uma versão um pouco melhorada - o padrão do módulo revelador de Christian Heilmann.
O padrão Revealing Module surgiu quando Heilmann ficou frustrado com o fato de ter que repetir o nome do objeto principal quando desejávamos chamar um método público de outro ou acessar variáveis públicas. objetar notação literal pelas coisas que ele desejava tornar públicas.
O resultado de seus esforços foi um padrão atualizado, onde simplesmente definimos todas as nossas funções e variáveis no escopo privado e retornamos um objeto anônimo com ponteiros para a funcionalidade privada que desejamos revelar como pública.
Um exemplo de como usar o padrão Revealing Module pode ser encontrado abaixo
Vantagens
Esse padrão permite que a sintaxe de nossos scripts seja mais consistente. Também fica mais claro no final do módulo quais de nossas funções e variáveis podem ser acessadas publicamente, o que facilita a legibilidade.
Desvantagens
Uma desvantagem desse padrão é que, se uma função privada se refere a uma função pública, essa função pública não pode ser substituída se um patch for necessário. Isso ocorre porque a função privada continuará se referindo à implementação privada e o padrão não se aplica aos membros públicos, apenas às funções.
Membros de objetos públicos que se referem a variáveis privadas também estão sujeitos às notas de regra sem patch acima.
fonte
Eu criei um namespace inspirado nos módulos de Erlang. É uma abordagem muito funcional, mas é assim que escrevo meu código JavaScript atualmente.
Ele fornece ao fechamento um espaço para nome global e expõe um conjunto de funções definidas dentro desse fechamento.
fonte
Depois de portar várias das minhas bibliotecas para projetos diferentes, e ter que mudar constantemente o espaço para nome de nível superior (nomeado estaticamente), passei a usar essa pequena função auxiliar (de código aberto) para definir espaços de nome.
A descrição dos benefícios está no meu blog . Você pode pegar o código fonte aqui .
Um dos benefícios de que realmente gosto é o isolamento entre os módulos em relação à ordem de carregamento. Você pode consultar um módulo externo ANTES de ser carregado. E a referência do objeto que você obtém será preenchida quando o código estiver disponível.
fonte
Eu uso a seguinte sintaxe para o espaço para nome.
jsfiddle: http://jsfiddle.net/rpaul/4dngxwb3/1/
fonte
Estou 7 anos atrasado para a festa, mas trabalhei bastante nisso há 8 anos:
É importante poder criar com facilidade e eficiência vários espaços para nome aninhados para manter um aplicativo Web complexo organizado e gerenciável, respeitando o espaço para nome global JavaScript (evitando a poluição do espaço para nome) e sem prejudicar nenhum objeto existente no caminho do espaço para nome. .
Do exposto acima, esta foi minha solução por volta de 2008:
Isso não está criando um espaço para nome, mas fornece uma função para criar espaços para nome.
Isso pode ser condensado em uma linha minificada:
Exemplo de uso:
Ou, como uma declaração:
Ou é então executado como:
Se você não precisar de suporte para navegadores herdados, uma versão atualizada:
Agora, eu ficaria desconfiado de expor
namespace
ao próprio espaço para nome global. (Pena que o idioma base não fornece isso para nós!) Portanto, eu normalmente usaria isso sozinho em um encerramento, como:Em um aplicativo maior, isso precisa ser definido apenas uma vez no início do carregamento da página (para aplicativos da Web baseados no cliente). Arquivos adicionais podem reutilizar a função de espaço para nome, se mantidos (incluído como "opcional" no acima). Na pior das hipóteses, se essa função for declarada novamente algumas vezes - são apenas algumas linhas de código e menos se minificadas.
fonte
Eu acho que todos vocês usam muito código para um problema tão simples. Não há necessidade de fazer um repo para isso. Aqui está uma função de linha única.
Tente :
fonte
Eu gosto da solução de Jaco Pretorius, mas queria tornar a palavra-chave "this" um pouco mais útil, apontando-a para o objeto module / namespace. Minha versão da frigideira:
fonte
Meu padrão favorito tornou-se recentemente:
Obviamente, o retorno pode estar no final, mas se apenas as declarações de funções o seguirem, é muito mais fácil ver qual é o espaço para nome e qual API está exposta.
O padrão de usar expressões de função nesses casos resulta em não ser possível saber quais métodos estão expostos sem passar por todo o código.
fonte
namespace.a();
Se estiver usando um Makefile, você pode fazer isso.
Prefiro usar um Makefile de qualquer maneira, quando chegar a cerca de 1000 linhas, porque posso comentar efetivamente grandes faixas de código removendo uma única linha no makefile. Isso facilita a mexer nas coisas. Além disso, com essa técnica, o espaço para nome aparece apenas uma vez no prelúdio, portanto é fácil alterar e você não precisa repeti-lo dentro do código da biblioteca.
Um script de shell para desenvolvimento ao vivo no navegador ao usar um makefile:
Adicione isso como uma tarefa make 'go' e você pode 'make go' para manter sua compilação atualizada enquanto codifica.
fonte
Bastante acompanhamento da resposta de Ionuț G. Stan, mas mostrando os benefícios do código não organizado usando
var ClassFirst = this.ClassFirst = function() {...}
, o que tira proveito do escopo de fechamento do JavaScript para menos confusão de espaço para nomes para classes no mesmo espaço para nome.Resultado:
fonte
Eu escrevi outra biblioteca de namespaces que funciona um pouco mais como os pacotes / unidades em outros idiomas. Ele permite que você crie um pacote de código JavaScript e a referência a esse pacote a partir de outro código:
Arquivo hello.js
Arquivo Example.js
Somente o segundo arquivo precisa ser incluído na página. Suas dependências (arquivo hello.js neste exemplo) serão carregadas automaticamente e os objetos exportados dessas dependências serão usados para preencher os argumentos da função de retorno de chamada.
Você pode encontrar o projeto relacionado em Pacotes JS .
fonte
Podemos usá-lo independentemente desta maneira:
fonte
Meu hábito é usar a função myName () como armazenamento de propriedades e, em seguida, var myName como titular do "método" ...
Se isso é legítimo o suficiente ou não, me bata! Eu confio na minha lógica PHP o tempo todo, e as coisas simplesmente funcionam. : D
if (this !== that) myObj.fName1(); else myObj.fName2();
Referência a isto: JavaScript: Criando Objeto com Object.create ()
fonte
No JavaScript, não há métodos predefinidos para usar espaços de nome. Em JavaScript, precisamos criar nossos próprios métodos para definir NameSpaces. Aqui está um procedimento que seguimos nas tecnologias Oodles.
Registrar um espaço para nome A seguir, é a função para registrar um espaço para nome
Para registrar um espaço para nome, basta chamar a função acima com o argumento como espaço para nome separado por
'.'
(ponto). Por exemplo, deixe o nome do seu aplicativo ser grande. Você pode criar um espaço para nome seguindo o métodoBasicamente, ele criará sua estrutura NameSpaces como abaixo no back-end:
Na função acima, você registrou um espaço para nome chamado
"oodles.HomeUtilities"
e"oodles.GlobalUtilities"
. Para chamar esses namespaces, criamos uma variável ie var$OHU
e var$OGU
.Essas variáveis nada mais são do que um alias para inicializar o espaço para nome. Agora, sempre que você declarar uma função que pertence a
HomeUtilities
você, a declarará da seguinte maneira:Acima está a inicialização do nome da função e é colocada em um espaço para nome
$OHU
. e chamar essa função em qualquer lugar dos arquivos de script. Basta usar o seguinte código.Da mesma forma, com os outros NameSpaces.
Espero que ajude.
fonte
JavaScript não suporta namespace por padrão. Portanto, se você criar qualquer elemento (função, método, objeto, variável), ele se tornará global e poluirá o espaço para nome global. Vamos dar um exemplo de definição de duas funções sem nenhum espaço para nome,
Ele sempre chama a segunda definição de função. Nesse caso, o namespace resolverá o problema de colisão de nomes.
fonte