¿Cómo puedo crear variables estáticas en Javascript?
javascript
variables
static
closures
Rajat
fuente
fuente
someFunc = () => { MyClass.myStaticVariable = 1; }
. Luego, simplemente cree un método estático para devolver el miembro estático, por ejemplostatic getStatic() { return MyClass.myStaticVariable; }
. ¡Entonces puede llamarMyClass.getStatic()
desde fuera de la clase para obtener los datos estáticos!Respuestas:
Si proviene de un lenguaje orientado a objetos de tipo estático basado en clases (como Java, C ++ o C #) , supongo que está tratando de crear una variable o método asociado a un "tipo" pero no a una instancia.
Un ejemplo que utiliza un enfoque "clásico", con funciones de constructor, podría ayudarlo a captar los conceptos básicos de JavaScript OO:
staticProperty
está definido en el objeto MyClass (que es una función) y no tiene nada que ver con sus instancias creadas, JavaScript trata las funciones como objetos de primera clase , por lo que al ser un objeto, puede asignar propiedades a una función.ACTUALIZACIÓN: ES6 introdujo la capacidad de declarar clases a través de la
class
palabra clave. Es el azúcar de sintaxis sobre la herencia existente basada en prototipos.La
static
palabra clave le permite definir fácilmente propiedades estáticas o métodos en una clase.Veamos el ejemplo anterior implementado con las clases ES6:
fuente
privilegedMethod
no es equivalente a un método privado en OO porque parece que podría llamarse en una instancia de MyClass. ¿Quieres decir que es privilegiado porque puede accederprivateVariable
?this.constructor
puede utilizar para acceder a las variables estáticas desde los "métodos de instancia"? En caso afirmativo, vale la pena agregarlo a la respuesta.MyClass.prototype.staticProperty = "baz";
o para ser aún más correcto a los principios de OO, la propiedad estática debería definirse realmente como una función anónimaMyClass.prototype.staticProperty = function () {return staticVar;}
y para que todas las instancias accedan a una sola variable que también podría modificarse con un setter.Puede aprovechar el hecho de que las funciones JS también son objetos, lo que significa que pueden tener propiedades.
Por ejemplo, citando el ejemplo dado en el artículo (ahora desaparecido) Variables estáticas en Javascript :
Si llama a esa función varias veces, verá que el contador se está incrementando.
Y esta es probablemente una solución mucho mejor que contaminar el espacio de nombres global con una variable global.
Y aquí hay otra solución posible, basada en un cierre: truco para usar variables estáticas en javascript :
Lo que le da el mismo tipo de resultado, excepto que, esta vez, se devuelve el valor incrementado, en lugar de mostrarse.
fuente
countMyself.counter = countMyself.counter || initial_value;
si la variable estática nunca va a ser falsey (cadena falsa, 0, nula o vacía)===
para lostypeof
controles, de lo contrario obtendrá una coerción extraña.Lo haces a través de un IIFE (expresión de función invocada inmediatamente):
fuente
puede usar argumentos.callee para almacenar variables "estáticas" (esto también es útil en la función anónima):
fuente
arguments.callee
es obsoleto.callee
parecía algo bueno tener. Me pregunto por qué demonios decidieron desaprobar esto ...: |He visto un par de respuestas similares, pero me gustaría mencionar que esta publicación lo describe mejor, así que me gustaría compartirlo con ustedes.
Aquí hay un código extraído de él, que he modificado para obtener un ejemplo completo que, con suerte, beneficiará a la comunidad porque se puede usar como plantilla de diseño para las clases.
También responde a tu pregunta:
Dado ese ejemplo, puede acceder a las propiedades / funciones estáticas de la siguiente manera:
Y las propiedades / funciones del objeto simplemente como:
Tenga en cuenta que en podcast.immutableProp (), tenemos un cierre : la referencia a _somePrivateVariable se mantiene dentro de la función.
Incluso puede definir captadores y establecedores . Eche un vistazo a este fragmento de código (donde
d
está el prototipo del objeto para el que desea declarar una propiedad,y
es una variable privada no visible fuera del constructor):Define la propiedad a
d.year
través deget
yset
funciones: si no especificaset
, entonces la propiedad es de solo lectura y no puede modificarse (tenga en cuenta que no obtendrá un error si intenta configurarlo, pero no tiene ningún efecto). Cada propiedad tiene los atributoswritable
,configurable
(permitir al cambio después de la declaración) yenumerable
(permite utilizarlo como empadronador), que son por defectofalse
. Puede configurarlosdefineProperty
en el tercer parámetro, por ejemploenumerable: true
.Lo que también es válido es esta sintaxis:
que define una propiedad legible / grabable
a
, una propiedad de solo lecturab
y una propiedad de solo escriturac
, a través de la cuala
se puede acceder a la propiedad .Uso:
Notas:
Para evitar un comportamiento inesperado en caso de que haya olvidado la
new
palabra clave, le sugiero que agregue lo siguiente a la funciónPodcast
:Ahora las dos instancias siguientes funcionarán como se esperaba:
La declaración 'nuevo' crea un nuevo objeto y copia todas las propiedades y métodos, es decir
Tenga en cuenta también que , en algunas situaciones, puede ser útil utilizar la
return
instrucción en la función de constructorPodcast
para devolver un objeto personalizado que protege las funciones de las que depende internamente la clase pero que necesitan ser expuestas. Esto se explica más adelante en el capítulo 2 (Objetos) de la serie de artículos.Puedes decir eso
a
yb
heredar dePodcast
. Ahora, ¿qué sucede si desea agregar un método a Podcast que se aplique a todos ellos despuésa
yb
haya sido instanciado? En este caso, use lo.prototype
siguiente:Ahora llame
a
yb
otra vez:Puede encontrar más detalles sobre los prototipos aquí . Si desea hacer más herencia, le sugiero que investigue esto .
Se recomienda encarecidamente leer la serie de artículos que he mencionado anteriormente , que incluyen también los siguientes temas:
Tenga en cuenta que la "característica" de inserción automática de punto y coma de JavaScript (como se menciona en 6.) a menudo es responsable de causar problemas extraños en su código. Por lo tanto, prefiero considerarlo como un error que como una característica.
Si desea leer más, aquí hay un artículo de MSDN bastante interesante sobre estos temas, algunos de ellos descritos allí brindan aún más detalles.
Lo que también es interesante de leer (que también cubre los temas mencionados anteriormente) son los artículos de la Guía de JavaScript de MDN :
Si desea saber cómo emular
out
parámetros de C # (como enDateTime.TryParse(str, out result)
) en JavaScript, puede encontrar el código de muestra aquí.Aquellos de ustedes que están trabajando con IE (que no tiene consola para JavaScript a menos que abra las herramientas de desarrollador usando F12y abra la pestaña de la consola) pueden encontrar útil el siguiente fragmento. Le permite usar
console.log(msg);
como se usa en los ejemplos anteriores. Simplemente insértelo antes de laPodcast
función.Para su comodidad, aquí está el código anterior en un fragmento de código único completo:
Mostrar fragmento de código
Notas:
Algunos buenos consejos, sugerencias y recomendaciones sobre la programación de JavaScript en general se pueden encontrar aquí (prácticas recomendadas de JavaScript) y allí ('var' versus 'let') . También se recomienda este artículo sobre los tipos de letra implícitos (coerción) .
Una forma conveniente de usar clases y compilarlas en JavaScript es TypeScript. Aquí hay un patio de juegos donde puedes encontrar algunos ejemplos que te muestran cómo funciona. Incluso si no está utilizando TypeScript en este momento, puede echar un vistazo porque puede comparar TypeScript con el resultado de JavaScript en una vista de lado a lado. La mayoría de los ejemplos son simples, pero también hay un ejemplo de Raytracer que puede probar al instante. Recomiendo especialmente buscar en los ejemplos de "Uso de clases", "Uso de herencia" y "Uso de genéricos" seleccionándolos en el cuadro combinado: estas son plantillas agradables que puede usar instantáneamente en JavaScript. La mecanografía se usa con Angular.
Para lograr la encapsulación de variables locales, funciones, etc. en JavaScript, sugiero usar un patrón como el siguiente (JQuery usa la misma técnica):
Por supuesto, puede y debe colocar el código del script en un
*.js
archivo separado ; esto solo está escrito en línea para mantener el ejemplo corto.Las funciones de auto invocación (también conocidas como IIFE = Expresión de función invocada inmediatamente) se describen con más detalle aquí .
fuente
fuente
Respuesta actualizada:
En ECMAScript 6 , puede crear funciones estáticas usando la
static
palabra clave:Las clases de ES6 no introducen ninguna semántica nueva para las estadísticas. Puedes hacer lo mismo en ES5 así:
Puede asignar a una propiedad de
Foo
porque en JavaScript las funciones son objetos.fuente
Foo.bar;
devuelve la función asignada a él, no la cadena devuelta por la función como su comentario implica.bar
propiedad deFoo
que3
desea:Foo.bar = 3;
El siguiente ejemplo y explicación son del libro Professional JavaScript for Web Developers 2nd Edition de Nicholas Zakas. Esta es la respuesta que estaba buscando, así que pensé que sería útil agregarla aquí.
El
Person
constructor en este ejemplo tiene acceso al nombre de la variable privada, al igual que los métodosgetName()
ysetName()
. Con este patrón, la variable de nombre se vuelve estática y se usará entre todas las instancias. Esto significa que llamarsetName()
a una instancia afecta a todas las demás instancias. LlamarsetName()
o crear una nuevaPerson
instancia establece la variable de nombre en un nuevo valor. Esto hace que todas las instancias devuelvan el mismo valor.fuente
Si está utilizando la nueva sintaxis de clase , ahora puede hacer lo siguiente:
Esto crea efectivamente una variable estática en JavaScript.
fuente
MyClass
definida fuera del constructo de la clase.Si desea declarar variables estáticas para crear constantes en su aplicación, encontré lo siguiente como el enfoque más simplista
fuente
Sobre el
class
presentado por ECMAScript 2015. Las otras respuestas no son totalmente claras.Aquí hay un ejemplo que muestra cómo crear una var estática
staticVar
conClassName
.var
sintaxis:Para acceder a la variable estática, utilizamos la
.constructor
propiedad que devuelve una referencia a la función de constructor de objetos que creó la clase. Podemos llamarlo en las dos instancias creadas:fuente
Hay otras respuestas similares, pero ninguna de ellas me atrajo. Esto es lo que terminé con:
fuente
Además del resto, actualmente hay un borrador (propuesta de etapa 2 ) sobre las propuestas de ECMA que introduce
static
los campos públicos en las clases. ( se consideraron campos privados )Usando el ejemplo de la propuesta, la
static
sintaxis propuesta se verá así:y ser equivalente a lo siguiente que otros han destacado:
Luego puede acceder a través de
CustomDate.epoch
.Puede realizar un seguimiento de la nueva propuesta en
proposal-static-class-features
.Actualmente, babel admite esta característica con el complemento de propiedades de clase de transformación que puede usar. Además, aunque todavía está en progreso, lo
V8
está implementando .fuente
Puede crear una variable estática en JavaScript como esta a continuación. Aquí
count
está la variable estática.Puede asignar valores a la variable estática utilizando la
Person
función o cualquiera de las instancias:fuente
Si desea hacer una variable estática global:
Reemplace la variable con la siguiente:
fuente
Lo más parecido en JavaScript a una variable estática es una variable global; esta es simplemente una variable declarada fuera del alcance de una función u objeto literal:
La otra cosa que podría hacer sería almacenar variables globales dentro de un objeto literal como este:
Y luego acceder a la variabels como esto:
foo.bar
.fuente
Para condensar todos los conceptos de clase aquí, pruebe esto:
Bueno, otra forma de echar un vistazo a las mejores prácticas en estas cosas es ver cómo coffeescript traduce estos conceptos.
fuente
En JavaScript las variables son estáticas por defecto. Ejemplo :
El valor de x se incrementa en 1 cada 1000 milisegundos
. Imprimirá 1,2,3, etc.
fuente
Hay otro enfoque, que resolvió mis requisitos después de navegar por este hilo. Depende exactamente de lo que quiera lograr con una "variable estática".
La propiedad global sessionStorage o localStorage permite que los datos se almacenen durante la vida de la sesión, o durante un período indefinido más largo hasta que se borre explícitamente, respectivamente. Esto permite compartir datos entre todas las ventanas, marcos, paneles de pestañas, ventanas emergentes, etc. de su página / aplicación y es mucho más poderoso que una simple "variable estática / global" en un segmento de código.
Evita toda molestia con el alcance, la vida útil, la semántica, la dinámica, etc. de las variables globales de nivel superior, es decir, Window.myglobal. No sé cuán eficiente es, pero eso no es importante para cantidades modestas de datos, a las que se accede a tasas modestas.
Se accede fácilmente como "sessionStorage.mydata = cualquier cosa" y se recupera de manera similar. Consulte "JavaScript: la guía definitiva, sexta edición", David Flanagan, ISBN: 978-0-596-80552-4, Capítulo 20, sección 20.1. Esto se puede descargar fácilmente como PDF mediante una simple búsqueda, o en su suscripción a O'Reilly Safaribooks (vale su peso en oro).
fuente
La función / classes permite solo un constructor único para su alcance de objeto.
Function Hoisting, declarations & expressions
Cierres : las copias del cierre funcionan con datos conservados.
Clases de funciones ES5 : utiliza Object.defineProperty (O, P, Atributos)
Creé algunos métodos usando `` , para que cada vez pueda comprender fácilmente las clases de funciones.
El siguiente fragmento de código es para probar que cada instancia tiene su propia copia de miembros de instancia y miembros estáticos comunes.
Clases ES6: Las clases ES2015 son un simple azúcar sobre el patrón OO basado en prototipos. Tener una única forma declarativa conveniente hace que los patrones de clase sean más fáciles de usar y fomenta la interoperabilidad. Las clases admiten herencia basada en prototipos, super llamadas, instancias y métodos y constructores estáticos.
Ejemplo : consulte mi publicación anterior.
fuente
Hay 4 formas de emular variables estáticas locales de función en Javascript.
Método 1: uso de propiedades de objeto de función (admitido en navegadores antiguos)
Método 2: uso de un cierre, variante 1 (compatible con navegadores antiguos)
Método 3: uso de un cierre, variante 2 (también compatible con navegadores antiguos)
Método 4: uso de un cierre, variante 3 (requiere soporte para EcmaScript 2015)
fuente
Puede definir funciones estáticas en JavaScript utilizando la
static
palabra clave:Al momento de escribir esto, aún no puede definir propiedades estáticas (que no sean funciones) dentro de la clase. Las propiedades estáticas siguen siendo una propuesta de Etapa 3 , lo que significa que aún no forman parte de JavaScript. Sin embargo, no hay nada que le impida simplemente asignar a una clase como lo haría a cualquier otro objeto:
Nota final: tenga cuidado con el uso de objetos estáticos con herencia: todas las clases heredadas comparten la misma copia del objeto .
fuente
En JavaScript, no hay término o palabra clave estática, pero podemos poner dichos datos directamente en el objeto de función (como en cualquier otro objeto).
fuente
Uso muchas variables de función estática y es una verdadera lástima que JS no tenga un mecanismo incorporado para eso. Demasiado a menudo veo código donde las variables y funciones se definen en un ámbito externo a pesar de que solo se usan dentro de una función. Esto es feo, propenso a errores y solo busca problemas ...
Se me ocurrió el siguiente método:
Esto agrega un método 'estático' a todas las funciones (sí, simplemente relájese), cuando se lo llame, agregará un objeto vacío (_statics) al objeto de función y lo devolverá. Si se proporciona una función init, _statics se establecerá en el resultado init ().
Entonces puedes hacer:
Comparando esto con un IIFE, que es la otra respuesta correcta, tiene la desventaja de agregar una asignación y una en cada llamada de función y agregar un miembro '_ estático' a la función, sin embargo, hay algunas ventajas: los argumentos están ahí la parte superior no está en la función interna, el uso de un 'estático' en el código de la función interna es explícito con un '_s'. prefijo, y en general es más simple de ver y entender.
fuente
Resumen:
En
ES6
/ ES 2015, laclass
palabra clave se introdujo con unastatic
palabra clave acompañada . Tenga en cuenta que este es el azúcar sintáctico sobre el modelo de herencia prototípica que encarna javavscript. Lastatic
palabra clave funciona de la siguiente manera para los métodos:fuente
Usé el prototipo y así funcionó:
o usando un captador estático:
fuente
Los niveles de ventana son más o menos como estáticos en el sentido de que puede usar referencias directas y están disponibles para todas las partes de su aplicación
fuente
No existe una variable estática en Javascript. Este lenguaje está orientado a objetos basados en prototipos, por lo que no hay clases, sino prototipos desde donde los objetos se "copian".
Puede simularlos con variables globales o con prototipos (agregando una propiedad al prototipo):
fuente
Function.prototype
function circle() {}
|circle.prototype
El |circle.prototype.pi = 3.14
El |circle.prototype
El |Function.prototype
El |Function.__proto__
(si eso es lo que querías decir)Al trabajar con sitios web de MVC que usan jQuery, me gusta asegurarme de que las acciones de AJAX dentro de ciertos controladores de eventos solo se puedan ejecutar una vez que se haya completado la solicitud anterior. Utilizo una variable de objeto jqXHR "estática" para lograr esto.
Dado el siguiente botón:
Generalmente uso un IIFE como este para mi controlador de clics:
fuente
Si quieres usar un prototipo, entonces hay una manera
¡Al hacer esto, podrá acceder a la variable de contador desde cualquier instancia y cualquier cambio en la propiedad se reflejará de inmediato!
fuente