namespace - ¿Cómo declaro un espacio de nombres en JavaScript?
javascript this (27)
¿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 una manera más elegante o sucinta de hacer esto?
¿Hay una manera más elegante o sucinta de hacer esto?
Sí. Por ejemplo:
var your_namespace = your_namespace || {};
entonces puedes tener
var your_namespace = your_namespace || {};
your_namespace.Foo = {toAlert:''test''};
your_namespace.Bar = function(arg)
{
alert(arg);
};
with(your_namespace)
{
Bar(Foo.toAlert);
}
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):
/**
* My JavaScript application
*
* @module myapp
*/
/** @namespace Namespace for MYAPP classes and functions. */
var MYAPP = MYAPP || {};
/**
* A maths utility
* @namespace MYAPP
* @class math_stuff
*/
MYAPP.math_stuff = {
/**
* Sums two numbers
*
* @method sum
* @param {Number} a First number
* @param {Number} b Second number
* @return {Number} Sum of the inputs
*/
sum: function (a, b) {
return a + b;
},
/**
* Multiplies two numbers
*
* @method multi
* @param {Number} a First number
* @param {Number} b Second number
* @return {Number} The inputs multiplied
*/
multi: function (a, b) {
return a * b;
}
};
/**
* Constructs Person objects
* @class Person
* @constructor
* @namespace MYAPP
* @param {String} First name
* @param {String} Last name
*/
MYAPP.Person = function (first, last) {
/**
* First name of the Person
* @property first_name
* @type String
*/
this.first_name = first;
/**
* Last name of the Person
* @property last_name
* @type String
*/
this.last_name = last;
};
/**
* Return Person''s full name
*
* @method getName
* @return {String} First name + last name
*/
MYAPP.Person.prototype.getName = function () {
return this.first_name + '' '' + this.last_name;
};
Bastante seguimiento de la respuesta de Ionuț G. Stan, pero que muestra los beneficios de un código var ClassFirst = this.ClassFirst = function() {...}
mediante el uso de var ClassFirst = this.ClassFirst = function() {...}
, que aprovecha el alcance del cierre de JavaScript para que no haya más espacio en el espacio de nombres para las clases en el mismo espacio de nombres.
var Namespace = new function() {
var ClassFirst = this.ClassFirst = function() {
this.abc = 123;
}
var ClassSecond = this.ClassSecond = function() {
console.log("Cluttered way to access another class in namespace: ", new Namespace.ClassFirst().abc);
console.log("Nicer way to access a class in same namespace: ", new ClassFirst().abc);
}
}
var Namespace2 = new function() {
var ClassFirst = this.ClassFirst = function() {
this.abc = 666;
}
var ClassSecond = this.ClassSecond = function() {
console.log("Cluttered way to access another class in namespace: ", new Namespace2.ClassFirst().abc);
console.log("Nicer way to access a class in same namespace: ", new ClassFirst().abc);
}
}
new Namespace.ClassSecond()
new Namespace2.ClassSecond()
Salida:
Cluttered way to access another class in namespace: 123
Nicer way to access a class in same namespace: 123
Cluttered way to access another class in namespace: 666
Nicer way to access a class in same namespace: 666
Creé un namespace 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.
Da un cierre a un espacio de nombres global y expone un conjunto definido de funciones dentro de ese cierre.
(function(){
namespace("images", previous, next);
// ^^ This creates or finds a root object, images, and binds the two functions to it.
// It works even though those functions are not yet defined.
function previous(){ ... }
function next(){ ... }
function find(){ ... } // A private function
})();
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 tener la intención de usar el espacio de namespace.namespace1
:
namespace = window.namespace || {};
namespace.namespace1 = namespace.namespace1 || {};
namespace.namespace1.doSomeThing = function(){}
Es posible que otro archivo desee utilizar el espacio de namespace.namespace2
:
namespace = window.namespace || {};
namespace.namespace2 = namespace.namespace2 || {};
namespace.namespace2.doSomeThing = function(){}
Estos dos archivos pueden vivir juntos o separados sin chocar.
Después de trasladar 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.
global_namespace.Define(''startpad.base'', function(ns) {
var Other = ns.Import(''startpad.other'');
....
});
La descripción de los beneficios está en mi blog . Puede 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 cargarlo. Y la referencia de objeto que obtenga se completará cuando el código esté disponible.
El patrón del Módulo se definió originalmente como una forma de proporcionar encapsulación tanto privada como pública para las clases en ingeniería de software convencional.
Cuando trabajamos con el patrón de Módulo, puede que nos resulte útil definir una plantilla simple que usamos para comenzar con ella. Aquí hay uno que cubre el espaciado de nombres, variables públicas y privadas.
En JavaScript, el patrón de 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. Lo que 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.
var myNamespace = (function () {
var myPrivateVar, myPrivateMethod;
// A private counter variable
myPrivateVar = 0;
// A private function which logs any arguments
myPrivateMethod = function( foo ) {
console.log( foo );
};
return {
// A public variable
myPublicVar: "foo",
// A public function utilizing privates
myPublicFunction: function( bar ) {
// Increment our private counter
myPrivateVar++;
// Call our private method using bar
myPrivateMethod( bar );
}
};
})();
Ventajas
¿Por qué el patrón del módulo es una buena elección? Para empezar, es mucho más limpio para los desarrolladores que vienen de un fondo orientado a objetos que la idea de la verdadera encapsulación, al menos desde una perspectiva de JavaScript.
En segundo lugar, admite datos privados; por lo tanto, en el patrón del 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 se sintió frustrado por el hecho de que tuvo que repetir el nombre del objeto principal cuando quisimos llamar a un método público desde otro o acceder a las variables públicas. También le disgustó 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 deseamos revelar como pública.
Un ejemplo de cómo usar el patrón del módulo revelador se puede encontrar a continuación.
var myRevealingModule = (function () {
var privateVar = "Ben Cherry",
publicVar = "Hey there!";
function privateFunction() {
console.log( "Name:" + privateVar );
}
function publicSetName( strName ) {
privateVar = strName;
}
function publicGetName() {
privateFunction();
}
// Reveal public pointers to
// private functions and properties
return {
setName: publicSetName,
greeting: publicVar,
getName: publicGetName
};
})();
myRevealingModule.setName( "Paul Kinlan" );
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 a cuál de nuestras funciones y variables se puede 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 ser anulada 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 de no parche anteriores.
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 utilizando este sencillo ayudante de JavaScript para mi pequeño proyecto y hasta ahora parece ser ligero pero lo suficientemente versátil como para manejar espacios de nombres y cargar módulos / clases. Sería genial si me permitiera importar un paquete a un espacio de nombres de mi elección, no solo el espacio de nombres global ... suspiro, pero eso no es lo importante.
Le permite declarar el espacio de nombres y luego definir objetos / módulos en ese espacio de nombres:
Namespace(''my.awesome.package'');
my.awesome.package.WildClass = {};
Otra opción es declarar el espacio de nombres y su contenido a la vez:
Namespace(''my.awesome.package'', {
SuperDuperClass: {
saveTheDay: function() {
alert(''You are welcome.'');
}
}
});
Para ver más ejemplos de uso, mira el archivo example.js en la fuente .
Llegué 7 años tarde a la fiesta, pero hice un poco de trabajo sobre esto hace 8 años:
- http://blogger.ziesemer.com/2008/05/javascript-namespace-function.html
- http://blogger.ziesemer.com/2007/10/respecting-javascript-global-namespace.html
Es importante poder crear de forma 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 obstruir ningún objeto existente en la ruta del espacio de nombres al hacerlo. .
De lo anterior, esta fue mi solución circa-2008:
var namespace = function(name, separator, container){
var ns = name.split(separator || ''.''),
o = container || window,
i,
len;
for(i = 0, len = ns.length; i < len; i++){
o = o[ns[i]] = o[ns[i]] || {};
}
return o;
};
Esto no crea un espacio de nombres, pero proporciona una función para crear espacios de nombres.
Esto se puede condensar en una sola línea minificada:
var namespace=function(c,f,b){var e=c.split(f||"."),g=b||window,d,a;for(d=0,a=e.length;d<a;d++){g=g[e[d]]=g[e[d]]||{}}return g};
Ejemplo de uso:
namespace("com.example.namespace");
com.example.namespace.test = function(){
alert("In namespaced function.");
};
O, como una declaración:
namespace("com.example.namespace").test = function(){
alert("In namespaced function.");
};
Cualquiera de los dos se ejecuta como:
com.example.namespace.test();
Si no necesita soporte para navegadores heredados, una versión actualizada:
const namespace = function(name, separator, container){
var o = container || window;
name.split(separator || ''.'').forEach(function(x){
o = o[x] = o[x] || {};
});
return o;
};
Ahora, estaría receloso de exponer el namespace
de namespace
al propio espacio de nombres global. (¡Lástima que el lenguaje base no nos proporcione esto!) Por lo tanto, normalmente lo uso yo mismo en un cierre, como:
(function(){
const namespace = function(name, separator, container){
var o = container || window;
name.split(separator || ''.'').forEach(function(x){
o = o[x] = o[x] || {};
});
return o;
};
const ns = namespace("com.ziesemer.myApp");
// Optional:
ns.namespace = ns;
// Further extend, work with ns from here...
}());
console.log("/"com/":", com);
En una aplicación más grande, esto solo debe definirse una vez al principio de la carga de una página (para aplicaciones web basadas en el cliente). Luego, 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 unas cuantas veces, es solo unas pocas líneas de código, y menos si se minimiza.
Me gusta esto:
var yourNamespace = {
foo: function() {
},
bar: function() {
}
};
...
yourNamespace.foo();
Me gusta la solución de Jaco Pretorius, pero quería hacer que la palabra clave "this" sea un poco más útil apuntándola al módulo / objeto de espacio de nombres. Mi versión de sartén:
(function ($, undefined) {
console.log(this);
}).call(window.myNamespace = window.myNamespace || {}, jQuery);
Mi patrón favorito se ha convertido últimamente en esto:
var namespace = (function() {
// expose to public
return {
a: internalA,
c: internalC
}
// all private
/**
* Full JSDoc
*/
function internalA() {
// ...
}
/**
* Full JSDoc
*/
function internalB() {
// ...
}
/**
* Full JSDoc
*/
function internalC() {
// ...
}
/**
* Full JSDoc
*/
function internalD() {
// ...
}
})();
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 uso de expresiones de función en tales casos resulta en no poder saber qué métodos se exponen sin pasar por todo el código.
Muestra:
var namespace = {};
namespace.module1 = (function(){
var self = {};
self.initialized = false;
self.init = function(){
setTimeout(self.onTimeout, 1000)
};
self.onTimeout = function(){
alert(''onTimeout'')
self.initialized = true;
};
self.init(); /* If it needs to auto-initialize, */
/* You can also call ''namespace.module1.init();'' from outside the module. */
return self;
})()
Opcionalmente, puede declarar una variable local
, same
, como self
y asignar local.onTimeout
si desea que sea privada.
Normalmente lo construyo en un cierre:
var MYNS = MYNS || {};
MYNS.subns = (function() {
function privateMethod() {
// Do private stuff, or build internal.
return "Message";
}
return {
someProperty: ''prop value'',
publicMethod: function() {
return privateMethod() + " stuff";
}
};
})();
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 de esta manera:
var MYNS = MYNS || {};
MYNS.subns = (function() {
var internalState = "Message";
var privateMethod = function() {
// Do private stuff, or build internal.
return internalState;
};
var publicMethod = function() {
return privateMethod() + " stuff";
};
return {
someProperty: ''prop value'',
publicMethod: publicMethod
};
})();
De esta manera, encuentro la API pública y la implementación más fáciles de entender. Piense en la declaración de devolución como una interfaz pública para la implementación.
Otra forma de hacerlo, que considero que es un poco menos restrictiva que la forma literal del objeto, es esta:
var ns = new function() {
var internalFunction = function() {
};
this.publicFunction = function() {
};
};
Lo anterior es muy parecido al patrón del módulo y, le guste o no , le permite exponer todas sus funciones como públicas, mientras evita la estructura rígida de un objeto literal.
Puede declarar una función simple para proporcionar espacios de nombres.
function namespace(namespace) {
var object = this, tokens = namespace.split("."), token;
while (tokens.length > 0) {
token = tokens.shift();
if (typeof object[token] === "undefined") {
object[token] = {};
}
object = object[token];
}
return object;
}
// Usage example
namespace("foo.bar").baz = "I''m a value!";
Si necesitas el ámbito privado:
var yourNamespace = (function() {
//Private property
var publicScope = {};
//Private property
var privateProperty = "aaa";
//Public property
publicScope.publicProperty = "bbb";
//Public method
publicScope.publicMethod = function() {
this.privateMethod();
};
//Private method
function privateMethod() {
console.log(this.privateProperty);
}
//Return only the public parts
return publicScope;
}());
yourNamespace.publicMethod();
de lo contrario, si nunca utilizará el ámbito privado:
var yourNamespace = {};
yourNamespace.publicMethod = function() {
// Do something...
};
yourNamespace.publicMethod2 = function() {
// Do something...
};
yourNamespace.publicMethod();
Tienes que revisar smith/namespacedotjs fuera!
Utilizo el enfoque que se encuentra en el sitio de 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.
(function( skillet, $, undefined ) {
//Private Property
var isHot = true;
//Public Property
skillet.ingredient = "Bacon Strips";
//Public Method
skillet.fry = function() {
var oliveOil;
addItem( "/t/n Butter /n/t" );
addItem( oliveOil );
console.log( "Frying " + skillet.ingredient );
};
//Private Method
function addItem( item ) {
if ( item !== undefined ) {
console.log( "Adding " + $.trim(item) );
}
}
}( window.skillet = window.skillet || {}, jQuery ));
Entonces, si desea acceder a uno de los miembros públicos, simplemente iría skillet.fry()
o skillet.ingredients
.
Lo que es realmente genial es que ahora puede ampliar el espacio de nombres usando la misma sintaxis.
//Adding new Functionality to the skillet
(function( skillet, $, undefined ) {
//Private Property
var amountOfGrease = "1 Cup";
//Public Method
skillet.toString = function() {
console.log( skillet.quantity + " " +
skillet.ingredient + " & " +
amountOfGrease + " of Grease" );
console.log( isHot ? "Hot" : "Cold" );
};
}( window.skillet = window.skillet || {}, jQuery ));
El tercer argumento undefined
El tercer argumento,
undefined
, es la fuente de la variable de valorundefined
. No estoy seguro de si sigue siendo relevante hoy en día, pero al trabajar con navegadores / estándares de JavaScript más antiguos (ecmascript 5, javascript <1.8.5 ~ firefox 4), la variable de alcance globalundefined
se puede escribir, por lo que cualquier persona puede volver a escribir su valor. El tercer argumento (cuando no se pasa un valor) crea una variable denominadaundefined
que está dentro del ámbito del espacio de nombres / función. Como no se pasó ningún valor cuando creó el espacio de nombres, el valor predeterminado es el valorundefined
.
Yo uso este enfoque:
var myNamespace = {}
myNamespace._construct = function()
{
var staticVariable = "This is available to all functions created here"
function MyClass()
{
// Depending on the class, we may build all the classes here
this.publicMethod = function()
{
//Do stuff
}
}
// Alternatively, we may use a prototype.
MyClass.prototype.altPublicMethod = function()
{
//Do stuff
}
function privateStuff()
{
}
function publicStuff()
{
// Code that may call other public and private functions
}
// List of things to place publically
this.publicStuff = publicStuff
this.MyClass = MyClass
}
myNamespace._construct()
// The following may or may not be in another file
myNamespace.subName = {}
myNamespace.subName._construct = function()
{
// Build namespace
}
myNamespace.subName._construct()
El código externo puede ser:
var myClass = new myNamespace.MyClass();
var myOtherClass = new myNamepace.subName.SomeOtherClass();
myNamespace.subName.publicOtherStuff(someParameter);
Yo uso la siguiente sintaxis para el espacio de nombres.
var MYNamespace = MYNamespace|| {};
MYNamespace.MyFirstClass = function (val) {
this.value = val;
this.getValue = function(){
return this.value;
};
}
var myFirstInstance = new MYNamespace.MyFirstClass(46);
alert(myFirstInstance.getValue());
jsfiddle: http://jsfiddle.net/rpaul/4dngxwb3/1/
Podemos usarlo independientemente de esta manera:
var A = A|| {};
A.B = {};
A.B = {
itemOne: null,
itemTwo: null,
};
A.B.itemOne = function () {
//..
}
A.B.itemTwo = function () {
//..
}
Si usas un Makefile puedes hacer esto.
// prelude.hjs
billy = new (
function moduleWrapper () {
const exports = this;
// postlude.hjs
return exports;
})();
// someinternalfile.js
function bob () { console.log(''hi''); }
exports.bob = bob;
// clientfile.js
billy.bob();
Prefiero usar un Makefile de todos modos una vez que llego a aproximadamente 1000 líneas porque puedo comentar efectivamente grandes franjas de código al eliminar una sola línea en el makefile. Hace que sea fácil jugar con las 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 tienes que repetirlo dentro del código de la biblioteca.
Un script de shell para el desarrollo en vivo en el navegador cuando se utiliza un makefile:
while (true); do make; sleep 1; done
Agregue esto como una tarea de make ''go'' y puede ''make go'' para mantener su compilación actualizada a medida que codifica.
Creo que todos ustedes usan demasiado código para un problema tan simple. No hay necesidad de hacer un repo para eso. Aquí hay una función de una sola línea.
namespace => namespace.split(".").reduce((last, next) => (last[next] = (last[next] || {})), window);
Intentalo :
// --- definition ---
const namespace = namespace => namespace.split(".").reduce((last, next) => (last[next] = (last[next] || {})), window);
// --- Use ----
let myNamespace = namespace("a.b.c");
myNamespace.MyClass = class MyClass {};
// --- see ----
console.log("a : ", a);
En JavaScript no hay métodos predefinidos para usar espacios de nombres. En JavaScript tenemos que crear nuestros propios métodos para definir espacios de nombres. Aquí hay un procedimiento que seguimos en las tecnologías de Oodles.
Registrar un espacio de nombres A continuación se muestra la función para registrar un espacio de nombres.
//Register NameSpaces Function
function registerNS(args){
var nameSpaceParts = args.split(".");
var root = window;
for(var i=0; i < nameSpaceParts.length; i++)
{
if(typeof root[nameSpaceParts[i]] == "undefined")
root[nameSpaceParts[i]] = new Object();
root = root[nameSpaceParts[i]];
}
}
Para registrar un espacio de nombre, simplemente llame a la función anterior con el argumento como espacio de nombre separado por ''.''
(punto). Por ejemplo, deje que su nombre de aplicación sea montones. Puedes hacer un espacio de nombres siguiendo el método
registerNS("oodles.HomeUtilities");
registerNS("oodles.GlobalUtilities");
var $OHU = oodles.HomeUtilities;
var $OGU = oodles.GlobalUtilities;
Básicamente, creará su estructura NameSpaces como a continuación en el backend:
var oodles = {
"HomeUtilities": {},
"GlobalUtilities": {}
};
En la función anterior tienes registrado un espacio de nombres llamado "oodles.HomeUtilities"
y "oodles.GlobalUtilities"
. Para llamar a estos espacios de nombres creamos una variable, es decir, var $OHU
y var $OGU
.
Estas variables no son más que un alias para Intializar el espacio de nombres. Ahora, siempre que declare una función que le pertenezca HomeUtilities
, la declarará así:
$OHU.initialization = function(){
//Your Code Here
};
Arriba está la inicialización del nombre de la función y se coloca en un espacio de nombres $OHU
. y para llamar a esta función en cualquier lugar en los archivos de script. Solo usa el siguiente código.
$OHU.initialization();
Del mismo modo, con el otro NameSpaces.
Espero eso ayude.
He escrito otra biblioteca de espacios de nombres que funciona un poco más como los paquetes / unidades en otros idiomas. Le permite crear un paquete de código JavaScript y la referencia de ese paquete desde otro código:
Archivo hello.js
Package("hello", [], function() {
function greeting() {
alert("Hello World!");
}
// Expose function greeting to other packages
Export("greeting", greeting);
});
Archivo Example.js
Package("example", ["hello"], function(greeting) {
// Greeting is available here
greeting(); // Alerts: "Hello World!"
});
Solo el segundo archivo debe ser incluido 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 utilizarán para rellenar los argumentos de la función de devolución de llamada.
Puede encontrar el proyecto relacionado en los Paquetes JS .
Mi hábito 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, me ganas! Estoy confiando en mi lógica PHP todo el tiempo, y las cosas simplemente funcionan. :RE
function myObj() {
this.prop1 = 1;
this.prop2 = 2;
this.prop3 = ''string'';
}
var myObj = (
(myObj instanceof Function !== false)
? Object.create({
$props: new myObj(),
fName1: function() { /* code.. */ },
fName2: function() { /* code ...*/ }
})
: console.log(''Object creation failed!'')
);
if (this !== that) myObj.fName1(); else myObj.fName2();
También puede hacerlo de forma ''viceversa'' para verificar antes de la creación del objeto, que es mucho mejor :
function myObj() {
this.prop1 = 1;
this.prop2 = 2;
this.prop3 = ''string'';
}
var myObj = (
(typeof(myObj) !== "function" || myObj instanceof Function === false)
? new Boolean()
: Object.create({
$props: new myObj(),
init: function () { return; },
fName1: function() { /* code.. */ },
fName2: function() { /* code ...*/ }
})
);
if (myObj instanceof Boolean) {
Object.freeze(myObj);
console.log(''myObj failed!'');
debugger;
}
else
myObj.init();
Referencia a esto: JavaScript: Crear objeto con Object.create ()