una que propiedad property polyfill objeto mdn crear agregar javascript object defineproperty

javascript - que - object defineproperty polyfill



cómo usar JavaScript Object.defineProperty (6)

Básicamente, defineProperty es un método que toma 3 parámetros: un objeto, una propiedad y un descriptor. Lo que está sucediendo en esta llamada en particular es que la propiedad de "health" del player se asigna a 10 más 15 veces el nivel de ese jugador.

Miré a mi alrededor para Object.defineProperty cómo usar el método Object.defineProperty , 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, el get es lo que no puedo obtener (juego de palabras). ¿Como funciona?


Object.defineProperty () es una función global ... No está disponible dentro de la función que declara el objeto de otra manera. Tendrás que usarlo estáticamente ...


Ya que hizo una pregunta similar , vamos a ir paso a paso. Es un poco más largo, pero puede ahorrarle mucho más tiempo de lo que he gastado en escribir esto:

La propiedad es una característica OOP diseñada para la separación limpia del código del cliente. Por ejemplo, en una tienda virtual puede tener objetos como este:

function Product(name,price) { this.name = name; this.price = price; this.discount = 0; } var sneakers = new Product("Sneakers",20); // {name:"Sneakers",price:20,discount:0} var tshirt = new Product("T-shirt",10); // {name:"T-shirt",price:10,discount:0}

Luego, en su código de cliente (e-shop), puede agregar descuentos a sus productos:

function badProduct(obj) { obj.discount+= 20; ... } function generalDiscount(obj) { obj.discount+= 10; ... } function distributorDiscount(obj) { obj.discount+= 15; ... }

Más tarde, el propietario de la tienda en línea podría darse cuenta de que el descuento no puede ser mayor que, por ejemplo, el 80%. Ahora necesita encontrar CADA ocurrencia de la modificación de descuento en el código del cliente y agregar una línea

if(obj.discount>80) obj.discount = 80;

Luego, el propietario de la tienda en línea puede cambiar su estrategia, como "si el cliente es revendedor, el descuento máximo puede ser del 90%" . Y necesita realizar el cambio en varios lugares nuevamente, además debe recordar modificar estas líneas cada vez que se cambie la estrategia. Este es un mal diseño. Es por eso que la encapsulación es el principio básico de OOP. Si el constructor fue así:

function Product(name,price) { var _name=name, _price=price, _discount=0; this.getName = function() { return _name; } this.setName = function(value) { _name = value; } this.getPrice = function() { return _price; } this.setPrice = function(value) { _price = value; } this.getDiscount = function() { return _discount; } this.setDiscount = function(value) { _discount = value; } }

Luego, puede modificar los getDiscount ( acceso ) y setDiscount ( 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 los datos para mantener el código extensible. Entonces necesitas agregar muchos códigos que no hacen nada. Este es también un mal diseño, un antipatrón repetitivo . A veces no puedes simplemente refactorizar los campos para los métodos más tarde (el código de la tienda puede crecer o algún código de terceros puede depender de la versión anterior), por lo que la repetición es un mal menor aquí. Pero aún así, es malvado. Es por eso que las propiedades se introdujeron en muchos idiomas. Puedes conservar el código original, solo transforma el miembro de descuento en una propiedad con los bloques get y set :

function Product(name,price) { this.name = name; this.price = price; //this.discount = 0; // <- remove this line and refactor with the code below var _discount; // private member Object.defineProperty(this,"discount",{ get: function() { return _discount; }, set: function(value) { _discount = value; if(_discount>80) _discount = 80; } }); } // the client code 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

Tenga en cuenta la última pero una línea: la responsabilidad del valor de descuento correcto se movió del código del cliente (definición de e-shop) a la definición del producto. El producto es responsable de mantener la coherencia de sus miembros de datos. El buen diseño es (más o menos dicho) si el código funciona de la misma manera que nuestros pensamientos.

Mucho sobre las propiedades. Pero javascript es diferente de los lenguajes puros orientados a objetos como C # y codifica las funciones de forma 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 autoejecutables si su código puede ser utilizado en un cliente compilado de forma separada.

En Javascript , las propiedades estándar (miembro de datos con getter y setter descrito anteriormente) están definidas por el descriptor de acceso (en el enlace que tiene en su pregunta). Exclusivamente, puede usar el descriptor de datos (para que no pueda usar, por ejemplo, valor y establecer en la misma propiedad):

  • descriptor de acceso = obtener + establecer (ver el ejemplo anterior)
    • get debe ser una función; su valor de retorno se usa para leer la propiedad; si no se especifica, el valor predeterminado es indefinido , que se comporta como una función que devuelve indefinido
    • set debe ser una función; su parámetro se completa con RHS al asignar un valor a la propiedad; si no se especifica, el valor predeterminado es indefinido , que se comporta como una función vacía
  • descriptor de datos = valor + escribible (ver el ejemplo a continuación)
    • valor predeterminado no definido ; si son modificables , configurables y enumerables (ver abajo) son verdaderos, la propiedad se comporta como un campo de datos ordinario
    • escribible - predeterminado falso ; si no es cierto , la propiedad es de solo lectura; intento de escribir se ignora sin error *!

Ambos descriptores pueden tener estos miembros:

  • configurable - predeterminado falso ; si no es cierto, la propiedad no se puede eliminar; intento de eliminar se ignora sin error *!
  • enumerable - predeterminado falso ; si es verdadero, se repetirá en for(var i in theObject) ; si es falso, no se repetirá, pero todavía 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 esté atrapado en el bloque try-catch

Para leer estas configuraciones, use Object.getOwnPropertyDescriptor() .

Aprende con el ejemplo:

var o = {}; Object.defineProperty(o,"test",{ value: "a", configurable: true }); console.log(Object.getOwnPropertyDescriptor(o,"test")); // check the settings for(var i in o) console.log(o[i]); // nothing, o.test is not enumerable console.log(o.test); // "a" o.test = "b"; // o.test is still "a", (is not writable, no error) delete(o.test); // bye bye, o.test (was configurable) o.test = "b"; // o.test is "b" for(var i in o) console.log(o[i]); // "b", default fields are enumerable

Si no desea permitir que el código del cliente haga trampas, puede restringir el objeto en tres niveles de confinamiento:

  • Object.preventExtensions(yourObject) impide que se agreguen nuevas propiedades a yourObject . Use Object.isExtensible(<yourObject>) para verificar si el método fue utilizado en el objeto. La prevención es superficial (lea a continuación).
  • Object.seal(yourObject) igual que el anterior y las propiedades no se pueden eliminar (establece efectivamente configurable: false para todas las propiedades). Use Object.isSealed(<yourObject>) para detectar esta característica en el objeto. El sello es poco profundo (lea a continuación).
  • Object.freeze(yourObject) igual que el anterior y las propiedades no se pueden cambiar (establece de manera efectiva la capacidad de writable: false en todas las propiedades con el 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 en profundidad - clonación ). Use Object.isFrozen(<yourObject>) para detectarlo.

No necesita molestarse con esto si escribe algunas líneas divertidas. Pero si quiere codificar un juego (como mencionó en la pregunta vinculada), realmente debería preocuparse por el buen diseño. Intenta buscar algo sobre antipatterns y codifica el olor . Te ayudará a evitar situaciones como "¡Oh, necesito volver a escribir por completo mi código nuevamente!" , puede ahorrarte meses de desesperación si quieres codificar mucho. Buena suerte.


sí no hay más funciones que se extienden para setup setter & getter este es mi ejemplo Object.defineProperty (obj, name, func)

var obj = {}; [''data'', ''name''].forEach(function(name) { Object.defineProperty(obj, name, { get : function() { return ''setter & getter''; } }); }); console.log(obj.data); console.log(obj.name);


get es una función que se player.health cuando intentas leer el valor player.health , como en:

console.log(player.health);

En realidad, no es muy diferente de:

player.getHealth = function(){ return 10 + this.level*15; } console.log(player.getHealth());

Se establece lo contrario de get, que se usaría cuando se asigna al valor. Como no existe un setter, parece que la asignación a la salud del jugador no está destinada:

player.health = 5; // Doesn''t do anything, since there is no set function defined

Un ejemplo muy simple:

var player = { level: 5 }; Object.defineProperty(player, "health", { get: function() { return 10 + (player.level * 15); } }); console.log(player.health); // 85 player.level++; console.log(player.health); // 100 player.health = 5; // Does nothing console.log(player.health); // 100


defineProperty es un método en Object que te permite configurar las propiedades para cumplir algunos criterios. Aquí hay un ejemplo simple con un objeto empleado con dos propiedades firstName & lastName y anexa las dos propiedades anulando el método toString en el objeto.

var employee = { firstName: "Jameel", lastName: "Moideen" }; employee.toString=function () { return this.firstName + " " + this.lastName; }; console.log(employee.toString());

Obtendrás la salida como: Jameel Moideen

Voy a cambiar el mismo código usando defineProperty en el objeto

var employee = { firstName: "Jameel", lastName: "Moideen" }; Object.defineProperty(employee, ''toString'', { value: function () { return this.firstName + " " + this.lastName; }, writable: true, enumerable: true, configurable: true }); console.log(employee.toString());

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 el objeto json que tiene un valor que va a ser una función y tres parámetros escribibles, enumerables y configurable. Justo ahora acabo de declarar todo como verdadero.

Si ejecuta el ejemplo, obtendrá el resultado siguiente: Jameel Moideen

Vamos a entender por qué necesitamos las tres propiedades, como escritura, enumerable y configurable. Escritable Una de las partes más molestas de javascript es, si cambia la propiedad toString por otra cosa, por ejemplo

si ejecuta esto de nuevo, todo se rompe. Cambiemos la escritura a falso. Si ejecuta el mismo nuevamente 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, incluidas toString.

console.log(Object.keys(employee));

si establece enumerable en falso, puede ocultar la propiedad toString de todos los demás. Si ejecuta esto de nuevo obtendrá firstName, lastName configurable

si alguien más tarde redefinió el objeto en más adelante por ejemplo enumerable en verdadero y lo ejecuta. Puede ver que la propiedad toString apareció nuevamente.

var employee = { firstName: "Jameel", lastName: "Moideen" }; Object.defineProperty(employee, ''toString'', { value: function () { return this.firstName + " " + this.lastName; }, writable: false, enumerable: false, configurable: true }); //change enumerable to false Object.defineProperty(employee, ''toString'', { enumerable: true }); employee.toString="changed"; console.log(Object.keys(employee));

puede restringir este comportamiento estableciendo configurable en falso.

La referencia original de esta información es de mi blog personal