¿Cómo creo un espacio de nombres en JavaScript para que mis objetos y funciones no sean sobrescritos por otros objetos y funciones con el mismo nombre? He usado lo siguiente:
if (Foo == null || typeof(Foo) != "object") { var Foo = new Object();}
¿Hay alguna forma más elegante o sucinta de hacer esto?
javascript
namespaces
javascript-namespaces
Scott McKenzie
fuente
fuente
Respuestas:
Me gusta esto:
fuente
MyApp
, por ejemplo, enMyApp.Views.Profile = {}
lugar deMyApp.users = {}
yMyViews.Profile = {}
. No necesariamente que solo debe haber dos niveles de profundidad.Uso el enfoque que se encuentra en el sitio Enterprise jQuery :
Aquí está su ejemplo que muestra cómo declarar propiedades y funciones privadas y públicas. Todo se hace como una función anónima autoejecutable.
Entonces, si desea acceder a uno de los miembros públicos, simplemente vaya
skillet.fry()
oskillet.ingredients
.Lo realmente genial es que ahora puede extender el espacio de nombres usando exactamente la misma sintaxis.
El tercer
undefined
argumentofuente
undefined
argumento es la fuente de la variable de valorundefined
. Al trabajar con navegadores más antiguos / estándar de JavaScript (ecmascript 5, javascript <1.8.5 ~ firefox 4), la variable de alcance globalundefined
se puede escribir, por lo que cualquiera podría reescribir su valor. Agregar un tercer argumento adicional que no está pasando lo hace valiosoundefined
, por lo que estaba creando un espacio de nombresundefined
que no será reescrito por fuentes externas.window.skillet = window.skillet || {}
es que permite que múltiples scripts se agreguen de manera segura al mismo espacio de nombres cuando no saben de antemano en qué orden ejecutarán. Esto puede ser útil si desea poder reordenar sus inclusiones de script de forma arbitraria sin romper su código, o si desea cargar scripts de forma asincrónica con el atributo async y, por lo tanto, no tiene garantía sobre el orden de ejecución. Ver stackoverflow.com/questions/6439579/…Otra forma de hacerlo, que considero que es un poco menos restrictiva que la forma literal del objeto, es esta:
Lo anterior es muy similar al patrón del módulo y, le guste o no , le permite exponer todas sus funciones como público, evitando la estructura rígida de un objeto literal.
fuente
ns().publicFunction()
Es decir ...ns.publicFunction()
funciona.new
palabra clave delante de lafunction
palabra clave. Básicamente, lo que está haciendo es declarar una función anónima (y como función, también es un constructor), e inmediatamente la invoca como un constructor usandonew
. Como tal, el valor final que se almacena dentrons
es una instancia (única) de ese constructor anónimo. Espero que tenga sentido.Si. Por ejemplo:
entonces puedes tener
fuente
var your_namespace = your_namespace = your_namespace || {}
Normalmente lo construyo en un cierre:
Mi estilo a lo largo de los años ha tenido un cambio sutil desde que escribí esto, y ahora me encuentro escribiendo el cierre así:
De esta manera, encuentro que la API pública y la implementación son más fáciles de entender. Piense en la declaración de devolución como una interfaz pública para la implementación.
fuente
MYNS.subns = MYNS.subns || {}
?var foo = function
yfunction foo
son similares, son privados; Debido a la naturaleza de tipo dinámico de JavaScript, este último es un poco más rápido ya que omite algunas instrucciones en la mayoría de las tuberías de los intérpretes. Convar foo
, el sistema de tipos debe ser invocado para averiguar qué tipo se está asignando a dicha var, mientras que confunction foo
, el sistema de tipos sabe automáticamente que es una función, por lo que se saltan un par de llamadas de función, lo que se traduce en menos invocaciones de instrucciones de CPU comojmp
,pushq
,popq
, etc, que se traduce en una tubería de CPU más corta.function foo
sintaxis es más legible. Y todavía me gusta mi versión.Debido a que puede escribir diferentes archivos de JavaScript y luego combinarlos o no combinarlos en una aplicación, cada uno debe poder recuperar o construir el objeto de espacio de nombres sin dañar el trabajo de otros archivos ...
Un archivo podría intentar usar el espacio de nombres
namespace.namespace1
:Otro archivo puede querer usar el espacio de nombres
namespace.namespace2
:Estos dos archivos pueden vivir juntos o separados sin colisionar.
fuente
Así es como Stoyan Stefanov lo hace en su libro de Patrones de JavaScript que me pareció muy bueno (también muestra cómo hace comentarios que permiten la documentación de API generada automáticamente y cómo agregar un método al prototipo de un objeto personalizado):
fuente
Yo uso este enfoque:
El código externo puede ser:
fuente
ns = ns || {}
puede parecer más defensivo, puede conducir a otros resultados inesperados.Este es un seguimiento del enlace de user106826 a Namespace.js. Parece que el proyecto se trasladó a GitHub . Ahora es smith / namespacedotjs .
He estado usando este simple ayudante de JavaScript para mi pequeño proyecto y hasta ahora parece ser lo suficientemente ligero pero versátil como para manejar el espacio de nombres y cargar módulos / clases. Sería genial si me permitiera importar un paquete en un espacio de nombres de mi elección, no solo en el espacio de nombres global ... suspiro, pero eso no viene al caso.
Le permite declarar el espacio de nombres y luego definir objetos / módulos en ese espacio de nombres:
Otra opción es declarar el espacio de nombres y su contenido a la vez:
Para obtener más ejemplos de uso, mire el archivo example.js en la fuente .
fuente
Muestra:
Opcionalmente, puede declarar una
local
variable,same
comoself
y asignarlocal.onTimeout
si desea que sea privada.fuente
Puede declarar una función simple para proporcionar espacios de nombres.
fuente
Si necesita el ámbito privado:
de lo contrario, si nunca usará el ámbito privado:
fuente
El patrón Módulo se definió originalmente como una forma de proporcionar encapsulación tanto privada como pública para las clases de ingeniería de software convencional.
Cuando trabaje con el patrón Módulo, podemos encontrarnos útil para definir una plantilla simple que usamos para comenzar con él. Aquí hay uno que cubre el espaciado de nombres, las variables públicas y privadas.
En JavaScript, el patrón Módulo se usa para emular aún más el concepto de clases de tal manera que podamos incluir tanto métodos públicos / privados como variables dentro de un solo objeto, protegiendo así partes particulares del alcance global. Esto resulta en una reducción en la probabilidad de que nuestros nombres de funciones entren en conflicto con otras funciones definidas en scripts adicionales en la página.
Ventajas
¿Por qué el patrón Módulo es una buena opción? Para empezar, es mucho más limpio para los desarrolladores que provienen de un entorno orientado a objetos que la idea de una verdadera encapsulación, al menos desde una perspectiva de JavaScript.
En segundo lugar, admite datos privados, por lo que, en el patrón Módulo, las partes públicas de nuestro código pueden tocar las partes privadas, sin embargo, el mundo exterior no puede tocar las partes privadas de la clase.
Desventajas
Las desventajas del patrón del Módulo son que a medida que accedemos a los miembros públicos y privados de manera diferente, cuando deseamos cambiar la visibilidad, en realidad tenemos que hacer cambios en cada lugar donde se usó el miembro.
Tampoco podemos acceder a miembros privados en métodos que se agregan al objeto en un momento posterior . Dicho esto, en muchos casos el patrón del Módulo sigue siendo bastante útil y, cuando se usa correctamente, ciertamente tiene el potencial de mejorar la estructura de nuestra aplicación.
El patrón del módulo revelador
Ahora que estamos un poco más familiarizados con el patrón del módulo, echemos un vistazo a una versión ligeramente mejorada: el patrón del módulo revelador de Christian Heilmann.
El patrón del Módulo Revelador surgió cuando Heilmann estaba frustrado con el hecho de que tenía que repetir el nombre del objeto principal cuando queríamos llamar a un método público desde otro o acceder a variables públicas. También le disgustaba el requisito del patrón del Módulo para tener que cambiar objetar la notación literal de las cosas que deseaba hacer públicas.
El resultado de sus esfuerzos fue un patrón actualizado en el que simplemente definiríamos todas nuestras funciones y variables en el ámbito privado y devolveríamos un objeto anónimo con punteros a la funcionalidad privada que deseábamos revelar como pública.
Un ejemplo de cómo usar el patrón del Módulo Revelador se puede encontrar a continuación
Ventajas
Este patrón permite que la sintaxis de nuestros scripts sea más consistente. También deja más claro al final del módulo cuáles de nuestras funciones y variables se pueden acceder públicamente, lo que facilita la legibilidad.
Desventajas
Una desventaja de este patrón es que si una función privada se refiere a una función pública, esa función pública no puede anularse si es necesario un parche. Esto se debe a que la función privada seguirá haciendo referencia a la implementación privada y el patrón no se aplica a los miembros públicos, solo a las funciones.
Los miembros de objetos públicos que se refieren a variables privadas también están sujetos a las notas de la regla sin parche anteriores.
fuente
Creé un espacio de nombres inspirado en los módulos de Erlang. Es un enfoque muy funcional, pero así es como escribo mi código JavaScript en estos días.
Le da a un cierre un espacio de nombres global y expone un conjunto de funciones definidas dentro de ese cierre.
fuente
Después de portar varias de mis bibliotecas a diferentes proyectos, y tener que cambiar constantemente el espacio de nombres de nivel superior (con nombre estático), he cambiado a usar esta pequeña función auxiliar (de código abierto) para definir espacios de nombres.
La descripción de los beneficios se encuentra en mi blog . Puedes obtener el código fuente aquí .
Uno de los beneficios que realmente me gusta es el aislamiento entre módulos con respecto al orden de carga. Puede consultar un módulo externo ANTES de que se cargue. Y la referencia de objeto que obtenga se completará cuando el código esté disponible.
fuente
Yo uso la siguiente sintaxis para el espacio de nombres.
jsfiddle: http://jsfiddle.net/rpaul/4dngxwb3/1/
fuente
Llegué 7 años tarde a la fiesta, pero trabajé bastante por esto hace 8 años:
Es importante poder crear de manera fácil y eficiente múltiples espacios de nombres anidados para mantener una aplicación web compleja organizada y manejable, respetando el espacio de nombres global de JavaScript (evitando la contaminación del espacio de nombres) y sin bloquear ningún objeto existente en la ruta del espacio de nombres mientras lo hace. .
De lo anterior, esta fue mi solución circa-2008:
Esto no crea un espacio de nombres, sino que proporciona una función para crear espacios de nombres.
Esto se puede condensar en una sola línea minificada:
Ejemplo de uso:
O, como una declaración:
Luego se ejecuta como:
Si no necesita soporte para navegadores heredados, una versión actualizada:
Ahora, desconfiaría de exponerme
namespace
al propio espacio de nombres global. (¡Lástima que el idioma base no nos proporcione esto!) Por lo general, lo usaría yo mismo en un cierre, como:En una aplicación más grande, esto solo debe definirse una vez al comienzo de la carga de una página (para aplicaciones web basadas en el cliente). Los archivos adicionales pueden reutilizar la función de espacio de nombres si se mantienen (incluidos como "opcionales" en lo anterior). En el peor de los casos, si esta función se vuelve a declarar varias veces, solo son unas pocas líneas de código, y menos si se minimiza.
fuente
Creo que todos ustedes usan demasiado código para un problema tan simple. No es necesario hacer un repositorio para eso. Aquí hay una función de una sola línea.
Intentalo :
fuente
Me gusta la solución de Jaco Pretorius, pero quería hacer que la palabra clave "this" sea un poco más útil al señalarla al objeto de módulo / espacio de nombres. Mi versión de sartén:
fuente
Mi patrón favorito se ha convertido últimamente en esto:
Por supuesto, el retorno puede ser al final, pero si solo lo siguen las declaraciones de funciones, es mucho más fácil ver de qué se trata el espacio de nombres y qué API está expuesta.
El patrón de usar expresiones de función en tales casos resulta en no poder saber qué métodos están expuestos sin pasar por todo el código.
fuente
namespace.a();
Si usa un Makefile puede hacer esto.
Prefiero usar un Makefile de todos modos una vez que llegue a aproximadamente 1000 líneas porque puedo comentar efectivamente grandes extensiones de código eliminando una sola línea en el makefile. Hace que sea fácil jugar con cosas. Además, con esta técnica, el espacio de nombres solo aparece una vez en el preludio, por lo que es fácil de cambiar y no tiene que seguir repitiéndolo dentro del código de la biblioteca.
Un script de shell para el desarrollo en vivo en el navegador cuando se utiliza un archivo MAKE:
Agregue esto como una tarea de creación 'go' y puede 'hacer que funcione' para mantener su compilación actualizada mientras codifica.
fuente
Todo un seguimiento de la respuesta de Ionuț G. Stan, pero mostrando los beneficios del código ordenado mediante el uso
var ClassFirst = this.ClassFirst = function() {...}
, que aprovecha el alcance de cierre de JavaScript para un menor desorden de espacio de nombres para las clases en el mismo espacio de nombres.Salida:
fuente
He escrito otra biblioteca de espacios de nombres que funciona un poco más como lo hacen los paquetes / unidades en otros idiomas. Le permite crear un paquete de código JavaScript y la referencia a ese paquete desde otro código:
Archivo hello.js
Archivo Ejemplo.js
Solo el segundo archivo debe incluirse en la página. Sus dependencias (archivo hello.js en este ejemplo) se cargarán automáticamente y los objetos exportados desde esas dependencias se usarán para completar los argumentos de la función de devolución de llamada.
Puede encontrar el proyecto relacionado en Paquetes JS .
fuente
Podemos usarlo independientemente de esta manera:
fuente
Mi costumbre es usar la función myName () como almacenamiento de propiedades, y luego var myName como titular del "método" ...
Si esto es lo suficientemente legítimo o no, ¡golpéame! Confío en mi lógica PHP todo el tiempo, y las cosas simplemente funcionan. :RE
if (this !== that) myObj.fName1(); else myObj.fName2();
Referencia a esto: JavaScript: creación de objetos con Object.create ()
fuente
En JavaScript no hay métodos predefinidos para usar espacios de nombres. En JavaScript tenemos que crear nuestros propios métodos para definir NameSpaces. Aquí hay un procedimiento que seguimos en las tecnologías Oodles.
Registrar un espacio de nombres A continuación se muestra la función para registrar un espacio de nombres
Para registrar un espacio de nombres simplemente llame a la función anterior con el argumento como espacio de nombres separado por
'.'
(punto). Por ejemplo, deje que el nombre de su aplicación sea montones. Puede crear un espacio de nombres siguiendo el métodoBásicamente creará su estructura NameSpaces como se muestra a continuación en el backend:
En la función anterior tiene registrado un espacio de nombres llamado
"oodles.HomeUtilities"
y"oodles.GlobalUtilities"
. Para llamar a estos espacios de nombres hacemos una variable, es decir, var$OHU
y var$OGU
.Estas variables no son más que un alias para inicializar el espacio de nombres. Ahora, cada vez que declare una función que le pertenezca
HomeUtilities
, la declarará de la siguiente manera:Arriba está la inicialización del nombre de la función y se coloca en un espacio de nombres
$OHU
. y llamar a esta función en cualquier parte de los archivos de script. Solo usa el siguiente código.Del mismo modo, con el otro NameSpaces.
Espero eso ayude.
fuente
JavaScript no admite el espacio de nombres de forma predeterminada. Entonces, si crea cualquier elemento (función, método, objeto, variable), entonces se vuelve global y contamina el espacio de nombres global. Tomemos un ejemplo de definición de dos funciones sin ningún espacio de nombres,
Siempre llama a la segunda definición de función. En este caso, el espacio de nombres resolverá el problema de colisión de nombres.
fuente