Miré a mi alrededor para Object.defineProperty
saber cómo usar el método, pero no pude encontrar nada decente.
Alguien me dio este fragmento de código :
Object.defineProperty(player, "health", {
get: function () {
return 10 + ( player.level * 15 );
}
})
Pero no lo entiendo. Principalmente, esto get
es lo que no puedo obtener (juego de palabras). ¿Como funciona?
javascript
object
defineproperty
Enfriador de matemáticas
fuente
fuente
Respuestas:
Como usted hizo una pregunta similar , vamos a hacerlo paso a paso. Es un poco más largo, pero puede ahorrarle mucho más tiempo del que he dedicado a escribir esto:
La propiedad es una característica de OOP diseñada para una separación limpia del código del cliente. Por ejemplo, en algunas tiendas electrónicas puede tener objetos como este:
Luego, en su código de cliente (la tienda electrónica), puede agregar descuentos a sus productos:
Más tarde, el propietario de la tienda electrónica podría darse cuenta de que el descuento no puede ser superior al 80%. Ahora necesita encontrar CADA ocurrencia de la modificación del descuento en el código del cliente y agregar una línea
Luego, el propietario de la tienda electrónica puede cambiar aún más su estrategia, como "si el cliente es revendedor, el descuento máximo puede ser del 90%" . Y debe volver a hacer el cambio en varios lugares, además debe recordar modificar estas líneas cada vez que cambie la estrategia. Este es un mal diseño. Es por eso que la encapsulación es el principio básico de la POO. Si el constructor fuera así:
Entonces puede simplemente alterar los métodos
getDiscount
( accesor ) ysetDiscount
( mutador ). El problema es que la mayoría de los miembros se comportan como variables comunes, solo el descuento necesita atención especial aquí. Pero un buen diseño requiere la encapsulación de cada miembro de datos para mantener el código extensible. Por lo tanto, debe agregar mucho código que no hace nada. Este también es un mal diseño, un antipatrón repetitivo . A veces no puede simplemente refactorizar los campos a los métodos más tarde (el código de eshop puede crecer o algunos códigos de terceros pueden depender de la versión anterior), por lo que la placa repetitiva es menos malvada aquí. Pero aún así, es malo. Es por eso que las propiedades se introdujeron en muchos idiomas. Puede conservar el código original, simplemente transformar el miembro de descuento en una propiedad conget
yset
bloques:Tenga en cuenta la última pero una línea: la responsabilidad del valor de descuento correcto se trasladó del código del cliente (definición de tienda electrónica) a la definición del producto. El producto es responsable de mantener consistentes sus miembros de datos. Un buen diseño es (más o menos dicho) si el código funciona de la misma manera que nuestros pensamientos.
Mucho sobre propiedades. Pero JavaScript es diferente de los lenguajes orientados a objetos puros como C # y codifica las características de manera diferente:
En C # , la transformación de campos en propiedades es un cambio radical , por lo que los campos públicos deben codificarse como Propiedades implementadas automáticamente si su código puede usarse en un cliente compilado por separado.
En Javascript , las propiedades estándar (miembro de datos con getter y setter descrito anteriormente) se definen por descriptor de acceso (en el enlace que tiene en su pregunta). Exclusivamente, puede usar el descriptor de datos (por lo que no puede usar, es decir, el valor y establecer en la misma propiedad):
Ambos descriptores pueden tener estos miembros:
for(var i in theObject)
; si es falso, no se repetirá, pero aún es accesible como público* a menos que esté en modo estricto : en ese caso, JS detiene la ejecución con TypeError a menos que se encuentre en el bloque try-catch
Para leer esta configuración, use
Object.getOwnPropertyDescriptor()
.Aprende con el ejemplo:
Si no desea permitir que el cliente codifique tales trucos, puede restringir el objeto por tres niveles de confinamiento:
Object.isExtensible(<yourObject>)
para verificar si el método se usó en el objeto. La prevención es poco profunda (lea a continuación).configurable: false
en todas las propiedades). UseObject.isSealed(<yourObject>)
para detectar esta característica en el objeto. El sello es poco profundo (lea a continuación).writable: false
en todas las propiedades con descriptor de datos). La propiedad de escritura de Setter no se ve afectada (ya que no tiene una). La congelación es superficial : significa que si la propiedad es Objeto, sus propiedades NO ESTÁN congeladas (si lo desea, debe realizar algo como "congelación profunda", similar a la copia profunda - clonación ). ÚseloObject.isFrozen(<yourObject>)
para detectarlo.No necesita molestarse con esto si solo escribe unas pocas líneas divertidas. Pero si desea codificar un juego (como mencionó en la pregunta vinculada), realmente debería preocuparse por un buen diseño. Intenta buscar en Google algo sobre antipatrones y código de olor . Le ayudará a evitar situaciones como "¡Oh, necesito reescribir completamente mi código nuevamente!" , puede ahorrarle meses de desesperación si desea codificar mucho. Buena suerte.
fuente
function Product(name,price) { this.name = name; this.price = price; var _discount; // private member Object.defineProperty(this,"discount",{ get: function() { return _discount; }, set: function(value) { _discount = value; if(_discount>80) _discount = 80; } }); } var sneakers = new Product("Sneakers",20); sneakers.discount = 50; // 50, setter is called sneakers.discount+= 20; // 70, setter is called sneakers.discount+= 20; // 80, not 90! alert(sneakers.discount); // getter is called
get
es una función que se llama cuando intentas leer el valorplayer.health
, como en:Efectivamente, no es muy diferente a:
Se establece lo contrario de get, que se usaría cuando asigne el valor. Como no hay setter, parece que la asignación a la salud del jugador no tiene la intención:
Un ejemplo muy simple:
fuente
()
para llamar ... No entiendo cuál fue la idea cuando inventaron esto. Las funciones son totalmente iguales: jsbin.com/bugipi/edit?js,console,outputdefineProperty es un método en Object que le permite configurar las propiedades para cumplir con algunos criterios. Aquí hay un ejemplo simple con un objeto de empleado con dos propiedades firstName y lastName y agregue las dos propiedades anulando el método toString en el objeto.
Obtendrá salida como: Jameel Moideen
Voy a cambiar el mismo código usando defineProperty en el objeto
El primer parámetro es el nombre del objeto y luego el segundo parámetro es el nombre de la propiedad que estamos agregando, en nuestro caso es toString y luego el último parámetro es un objeto json que tiene un valor que va a ser una función y tres parámetros escribibles, enumerables y configurable. En este momento acabo de declarar todo como verdadero.
Si ejecuta el ejemplo, obtendrá Output como: Jameel Moideen
Comprendamos por qué necesitamos las tres propiedades, como escritura, enumerable y configurable.
grabable
Una de las partes muy molestas de JavaScript es, si cambia la propiedad toString a otra cosa, por ejemplo
Si ejecuta esto de nuevo, todo se rompe. Cambiemos de escritura a falso. Si vuelve a ejecutar lo mismo, obtendrá la salida correcta como 'Jameel Moideen'. Esta propiedad evitará sobrescribir esta propiedad más adelante.
enumerable
Si imprime todas las claves dentro del objeto, puede ver todas las propiedades, incluyendo toString.
si establece enumerable en falso, puede ocultar la propiedad toString de todos los demás. Si ejecuta esto nuevamente, obtendrá firstName, lastName
configurable
si alguien más tarde redefinió el objeto más tarde, por ejemplo, enumerable a verdadero y lo ejecutó. Puede ver que la propiedad toString volvió a aparecer.
puede restringir este comportamiento configurando configurable en falso.
La referencia original de esta información es de mi blog personal
fuente
Básicamente,
defineProperty
es un método que toma 3 parámetros: un objeto, una propiedad y un descriptor. Lo que sucede en esta llamada en particular es que la"health"
propiedad delplayer
objeto se asigna a 10 más 15 veces el nivel de ese objeto jugador.fuente
sí, no más funciones que se extienden para el configurador y getter de configuración. Este es mi ejemplo Object.defineProperty (obj, name, func)
fuente
Object.defineProperty () es una función global ... No está disponible dentro de la función que declara el objeto de otra manera. Tendrá que usarlo estáticamente ...
fuente
Resumen:
Object.defineProperty
se utiliza para hacer una nueva propiedad en el objeto jugador.Object.defineProperty
es una función que está presente de forma nativa en el entorno de tiempo de ejecución JS y toma los siguientes argumentos:Object.defineProperty(obj, prop, descriptor)
El objeto descriptor es la parte interesante. Aquí podemos definir las siguientes cosas:
<boolean>
: sitrue
el descriptor de propiedad puede modificarse y la propiedad puede eliminarse del objeto. Si es configurable,false
las propiedades del descriptor que se pasanObject.defineProperty
no se pueden cambiar.<boolean>
: sitrue
la propiedad puede sobrescribirse utilizando el operador de asignación.<boolean>
: sitrue
la propiedad se puede iterar en unfor...in
bucle. Además, al usar laObject.keys
función, la tecla estará presente. Si la propiedad esfalse
, no se repetirán usando unfor..in
bucle y no se mostrarán cuando se useObject.keys
.<function>
: una función que se llama siempre que se requiera la propiedad. En lugar de dar el valor directo, se llama a esta función y el valor devuelto se da como el valor de la propiedad<function>
: una función que se llama siempre que se asigna la propiedad. En lugar de establecer el valor directo, se llama a esta función y el valor devuelto se utiliza para establecer el valor de la propiedad.Ejemplo:
fuente
fuente
Define una nueva propiedad directamente en un objeto, o modifica una propiedad existente en un objeto, y devuelve el objeto.
Explicación simple sobre definir propiedad.
Código de ejemplo: https://jsfiddle.net/manoj_antony32/pu5n61fs/
fuente
fuente