Para hacer una clase de JavaScript con un método público, haría algo como:
function Restaurant() {}
Restaurant.prototype.buy_food = function(){
// something here
}
Restaurant.prototype.use_restroom = function(){
// something here
}
De esa forma, los usuarios de mi clase pueden:
var restaurant = new Restaurant();
restaurant.buy_food();
restaurant.use_restroom();
¿Cómo creo un método privado que pueda ser llamado por los métodos buy_food
y use_restroom
pero no externamente por los usuarios de la clase?
En otras palabras, quiero que la implementación de mi método pueda hacer:
Restaurant.prototype.use_restroom = function() {
this.private_stuff();
}
Pero esto no debería funcionar:
var r = new Restaurant();
r.private_stuff();
¿Cómo lo defino private_stuff
como un método privado para que ambos sean válidos?
He leído el escrito de Doug Crockford varias veces, pero no parece que los métodos "privados" puedan llamarse mediante métodos públicos y los métodos "privilegiados" puedan llamarse externamente.
javascript
oop
private-methods
Wayne Kao
fuente
fuente
Uso de la función de invocación automática y llamada
JavaScript usa prototipos y no tiene clases (o métodos para el caso) como lenguajes orientados a objetos. Un desarrollador de JavaScript necesita pensar en JavaScript.
Cita de Wikipedia:
Solución que utiliza una función de invocación automática y la función de llamada para llamar al "método" privado:
La función de llamada nos permite llamar a la función privada con el contexto apropiado (
this
).Más simple con Node.js
Si está utilizando node.js , no necesita el IIFE porque puede aprovechar el sistema de carga del módulo :
Cargue el archivo
(experimental) ES7 con el operador Bind
El operador de enlace
::
es una propuesta ECMAScript y se implementa en Babel ( etapa 0 ).Cargue el archivo
fuente
.call
parte.f()
en javascript (no en este momento)..call
) y memoria pequeña (no hay funciones en la instancia)? ¿Eso incluso existe?Puede simular métodos privados como este:
Más información sobre esta técnica aquí: http://webreflection.blogspot.com/2008/04/natural-javascript-private-methods.html
fuente
En estas situaciones cuando tiene una API pública, y desea métodos / propiedades privadas y públicas, siempre uso el Patrón de módulo. Este patrón se hizo popular dentro de la biblioteca YUI, y los detalles se pueden encontrar aquí:
http://yuiblog.com/blog/2007/06/12/module-pattern/
Es realmente sencillo y fácil de comprender para otros desarrolladores. Por un simple ejemplo:
fuente
aPrivateMethod = function() { MYLIB.aPublicProperty}
:?Aquí está la clase que creé para comprender lo que Douglas Crockford ha sugerido en su sitio Miembros privados en JavaScript
fuente
that
se usa en lugar dethis
evitar problemas de alcance, cuando las funciones están vinculadas a un objeto diferente. Aquí, usted está almacenandothis
enthat
y nunca usarlo otra vez, que es lo mismo que no hacerlo en absoluto. Debe cambiarthis
conthat
todas lasConstructor
funciones internas (no la declaración de métodos). Siemployee
seapply
ed ocall
ed de alguna manera, estos métodos podrían arrojar yathis
que se vincularán incorrectamente.Conjuré esto: EDITAR: En realidad, alguien se ha vinculado a una solución idéntica. Duh!
fuente
var getAwayVehicle = new Car(100);
dónde100
está la velocidad y desea alertar la velocidad. ¡Gracias!var Car = function(speed) { this.speed = speed; }
y `return {constructor: Car, ...`Creo que esas preguntas surgen una y otra vez debido a la falta de comprensión de los cierres. Сlosures es lo más importante en JS. Cada programador de JS tiene que sentir la esencia de esto.
1. Primero que nada necesitamos hacer un alcance separado (cierre).
2. En esta área, podemos hacer lo que queramos. Y nadie lo sabrá.
3. Para que el mundo sepa sobre nuestra clase de restaurante, tenemos que devolverla del cierre.
4. Al final, tenemos:
5. Además, este enfoque tiene potencial para heredar y crear plantillas
Espero que esto ayude a alguien a entender mejor este tema
fuente
Personalmente, prefiero el siguiente patrón para crear clases en JavaScript:
Como puede ver, le permite definir propiedades de clase y propiedades de instancia, cada una de las cuales puede ser pública y privada.
Manifestación
Ver también este violín .
fuente
Todo este cierre te costará. Asegúrese de probar las implicaciones de velocidad, especialmente en IE. Encontrará que está mejor con una convención de nomenclatura. Todavía hay muchos usuarios corporativos que están obligados a usar IE6 ...
fuente
No seas tan detallado. Es Javascript. Use una convención de nomenclatura .
Después de años de trabajar en clases de es6, recientemente comencé a trabajar en un proyecto de es5 (usando requireJS que ya tiene un aspecto muy detallado). He estado una y otra vez todas las estrategias mencionadas aquí y básicamente todo se reduce a usar una convención de nomenclatura :
private
. Otros desarrolladores que ingresen a Javascript lo sabrán por adelantado. Por lo tanto, una simple convención de nomenclatura es más que suficiente. Una simple convención de nomenclatura de prefijos con un guión bajo resuelve el problema de las propiedades privadas y los métodos privados.my-tooltip.js
fuente
define
, yyconstructor
la estructura misma. Si bien estoy de acuerdo principalmente con la respuesta, comencé a trabajar con JS con mucha influencia de OOP e incluso salté demasiado temprano a TS ya que tenía experiencia previa en C #. Creo que tengo que desaprender estas cosas y tengo que entender el paradigma de prototipos / procedimientos. (Votado, por cierto)Puede hacerlo ahora con los métodos privados es10 . Solo necesita agregar un
#
antes del nombre del método.fuente
Tome cualquiera de las soluciones que siguen el patrón privado o privilegiado de Crockford . Por ejemplo:
En cualquier caso en el que el atacante no tenga "ejecutar" directamente en el contexto JS, no tiene forma de acceder a ningún campo o método "público" o "privado". En caso de que el atacante tenga ese acceso, puede ejecutar esta línea:
Tenga en cuenta que el código anterior es genérico para todo constructor-type-privacy. Fallará con algunas de las soluciones aquí, pero debe quedar claro que casi todas las soluciones basadas en el cierre pueden romperse de esta manera con diferentes
replace()
parámetros.Después de que esto se ejecute, cualquier objeto creado con
new Foo()
tendrá uneval
método al que se puede llamar para devolver o cambiar valores o métodos definidos en el cierre del constructor, por ejemplo:El único problema que puedo ver con esto es que no funcionará en los casos en que solo haya una instancia y se cree en carga. Pero entonces no hay ninguna razón para definir realmente un prototipo y en ese caso el atacante puede simplemente recrear el objeto en lugar del constructor, siempre que tenga una forma de pasar los mismos parámetros (por ejemplo, son constantes o se calculan a partir de los valores disponibles).
En mi opinión, esto hace que la solución de Crockford sea inútil.Dado que la "privacidad" se rompe fácilmente, las desventajas de su solución (menor legibilidad y facilidad de mantenimiento, menor rendimiento, mayor memoria) hacen que el método basado en el prototipo "sin privacidad" sea la mejor opción.
Usualmente uso guiones bajos para marcar
__private
y_protected
métodos y campos (estilo Perl), pero la idea de tener privacidad en JavaScript solo muestra cómo es un lenguaje incomprendido.Por lo tanto, no estoy de acuerdo con Crockford excepto por su primera oración.
Entonces, ¿cómo se obtiene privacidad real en JS? Ponga todo lo que se requiere para ser privado en el lado del servidor y use JS para hacer llamadas AJAX.
fuente
(function () {allMyStuff}());
para no exponer nada global.f.eval('nameOfVariable')
cuando no sabes qué'nameOfVariable'
es ...La apoteosis del patrón del módulo: el patrón del módulo revelador
Una pequeña extensión ordenada a un patrón muy robusto.
fuente
Si desea la gama completa de funciones públicas y privadas con la capacidad de las funciones públicas de acceder a funciones privadas, codifique el diseño de un objeto como este:
fuente
new MyObject
, el prototipo deMyObject
se reemplaza con los mismos valores..prototype
interior del constructor.Similar a georgebrock pero un poco menos detallado (en mi humilde opinión) ¿Algún problema para hacerlo de esta manera? (No lo he visto en ningún lado)
editar: me di cuenta de que esto es un poco inútil ya que cada instancia independiente tiene su propia copia de los métodos públicos, lo que socava el uso del prototipo.
fuente
Esto es lo que más he disfrutado hasta ahora con respecto a los métodos / miembros privados / públicos y la creación de instancias en javascript:
Aquí está el artículo: http://www.sefol.com/?p=1090
y aquí está el ejemplo:
JSFiddle: http://jsfiddle.net/northkildonan/kopj3dt3/1/
fuente
El patrón del módulo es correcto en la mayoría de los casos. Pero si tiene miles de instancias, las clases ahorran memoria. Si ahorrar memoria es una preocupación y sus objetos contienen una pequeña cantidad de datos privados, pero tienen muchas funciones públicas, entonces querrá que todas las funciones públicas vivan en el .prototype para ahorrar memoria.
Esto es lo que se me ocurrió:
El objeto
priv
contiene propiedades privadas. Es accesible a través de la función públicagetPriv()
, pero esta función regresa afalse
menos que la pasesecret
, y esto solo se conoce dentro del cierre principal.fuente
¿Qué hay de esto?
La búsqueda de variables privadas es imposible fuera del alcance de la función inmediata. No hay duplicación de funciones, ahorrando memoria.
La desventaja es que la búsqueda de variables privadas es torpe,
privateVars[this.id].cooked
es ridículo escribir. También hay una variable "id" adicional.fuente
Restaurant
comoundefined
porque no está devolviendo nada de la función anónima.Restaurant
se ha recogido basura, sus valores permanecen dentroprivateVars
. AWeakMap
puede ser un buen reemplazo para elArray
en este caso.Envuelva todo el código en Función anónima: entonces, todas las funciones serán privadas, SOLO las funciones adjuntas al
window
objeto:Utilizar este :
VIOLÍN
fuente
Prefiero almacenar datos privados en un asociado
WeakMap
. Esto le permite mantener sus métodos públicos en el prototipo al que pertenecen. Esta parece ser la forma más eficiente de manejar este problema para un gran número de objetos.fuente
Las funciones privadas no pueden acceder a las variables públicas utilizando el patrón de módulo
fuente
Como todos estaban publicando aquí su propio código, yo también lo haré ...
Me gusta Crockford porque introdujo patrones orientados a objetos reales en Javascript. Pero también se le ocurrió un nuevo malentendido, el "ese".
Entonces, ¿por qué está usando "that = this"? No tiene nada que ver con funciones privadas en absoluto. Tiene que ver con funciones internas!
Porque según Crockford, este es un código con errores:
Entonces sugirió hacer esto:
Entonces, como dije, estoy bastante seguro de que Crockford se equivocó en su explicación sobre eso y esto (pero su código es ciertamente correcto). ¿O simplemente estaba engañando al mundo de Javascript, para saber quién está copiando su código? No sé ... no soy un geek del navegador; D
EDITAR
Ah, de eso se trata: ¿qué significa 'var that = this;' significa en JavaScript?
Entonces Crockie estaba realmente equivocado con su explicación ... pero con su código, así que sigue siendo un gran tipo. :))
fuente
En general, agregué el objeto privado _ temporalmente al objeto. Debe abrir la privacidad exlipcitly en el "Power-constructor" para el método. Si llama al método desde el prototipo, podrá sobrescribir el método prototipo
Hacer accesible un método público en el "Constructor de energía": (ctx es el contexto del objeto)
Ahora tengo este openPrivacy:
fuente
Esto es lo que resolví:
Necesita una clase de código de azúcar que puede encontrar aquí . También admite material protegido, herencia, virtual, estático ...
fuente
https://github.com/nooning/JSClass
fuente
He creado una nueva herramienta para permitirle tener verdaderos métodos privados en el prototipo https://github.com/TremayneChrist/ProtectJS
Ejemplo:
fuente
_private
método?Debe cerrar su función de constructor real, donde puede definir sus métodos privados. Para cambiar los datos de las instancias a través de estos métodos privados, debe darles "esto" con ellos, ya sea como un argumento de función o llamando a esta función con .apply (this):
fuente
new Restaurant
tendrá su propiorestaurant
constructor, y el "prototipo" es totalmente abusado.Sé que es demasiado tarde, pero ¿qué tal esto?
fuente
Ya hay muchas respuestas sobre esta pregunta, pero nada satisfizo mis necesidades. Así que se me ocurrió mi propia solución, espero que sea útil para alguien:
Como puede ver, este sistema funciona cuando se usa este tipo de clases en JavaScript. Por lo que descubrí, ninguno de los métodos comentados anteriormente lo hizo.
fuente
Vea esta respuesta para obtener una solución limpia y simple de 'clase' con una interfaz pública y privada y soporte para la composición
fuente