cuando se utiliza el objeto.defineProperty()


Me pregunto cuándo debo usar

Object.defineProperty

Para crear nuevas propiedades para un objeto. Soy consciente de que soy capaz de establecer cosas como

enumerable: false

Pero ¿cuándo necesitas esto realmente? Si acaba de establecer una propiedad como

myObject.myprop = 5;

Sus descriptores están todos en true, ¿verdad? De hecho, tengo más curiosidad cuando ustedes usan esa llamada bastante detallada .defineProperty() y por qué razones.

Author: jAndy, 2012-04-11

7 answers

Object.defineProperty se utiliza principalmente para establecer propiedades con descriptores de propiedad específicos (por ejemplo, solo lectura (constantes), enumerabilidad( para no mostrar una propiedad en un for (.. in ..) loop, getters, setters).

"use strict";
var myObj = {}; // Create object
// Set property (+descriptor)
Object.defineProperty(myObj, 'myprop', {
    value: 5,
    writable: false
});
console.log(myObj.myprop);// 5
myObj.myprop = 1;         // In strict mode: TypeError: myObj.myprop is read-only

Ejemplo

Este método extiende el prototipo Object con una propiedad. Solo se define el getter, y la enumerabilidad se establece en false.

Object.defineProperty(Object.prototype, '__CLASS__', {
    get: function() {
        return Object.prototype.toString.call(this);
    },
    enumerable: false // = Default
});
Object.keys({});           // []
console.log([].__CLASS__); // "[object Array]"
 33
Author: Rob W,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-11 12:29:59

Características como 'enumerable' rara vez se utilizan en mi experiencia. El caso de uso principal son las propiedades calculadas:

var myObj = {};

myObj.width = 20;
myObj.height = 20;

Object.defineProperty(myObj, 'area', {
    get: function() {
        return this.width*this.height;
    }
});
console.log(myObj.area);
 20
Author: Pascalius,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-20 13:38:09

Una muy buena razón para usar Object.defineProperty es que le permite recorrer una función en un objeto como una propiedad calculada, que ejecuta la función en lugar de devolver el cuerpo de la función.

Por ejemplo:

var myObj = {};

myObj.width = 20;
myObj.height = 20;

Object.defineProperty(myObj, 'area', {
    get: function() {
        return this.width*this.height;
    },
    enumerable: true
});

for (var key in myObj) {
  if (myObj.hasOwnProperty(key)) {
    console.log(key + " -> " + myObj[key]);
  }
}
//width -> 20, height -> 20, area -> 400

Versus agregar la función como una propiedad a un objeto literal:

var myObj = {};

myObj.width = 20;
myObj.height = 20;

myObj.area = function() {
       return this.width*this.height;
    };

for (var key in myObj) {
  if (myObj.hasOwnProperty(key)) {
    console.log(key + " -> " + myObj[key]);
  }
}
// width -> 20, height -> 20, area -> function() { return this.width*this.height;}

Asegúrese de establecer la propiedad enumerable en true para recorrer el bucle.

 12
Author: Gerard Simpson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-06 11:37:51

Un buen caso de uso que he visto para defineProperty es que las bibliotecas proporcionen una propiedad de error al usuario que, si no se accede dentro de un cierto intervalo, se lanzaría usted mismo. Por ejemplo:

let logErrorTimeoutId = setTimeout(() => {
  if (error) {
    console.error('Unhandled (in <your library>)', error.stack || error);
  }
}, 10);

Object.defineProperty(data, 'error', {
    configurable: true,
    enumerable: true,
    get: () => {
      clearTimeout(logErrorTimeoutId);
      return error;
    },
  });

Fuente de este código: https://github.com/apollographql/react-apollo/blob/ddd3d8faabf135dca691d20ce8ab0bc24ccc414e/src/graphql.tsx#L510

 0
Author: Alfonso Pérez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-22 18:38:32

Un buen uso es cuando necesitas hacer alguna intercepción o aplicar un patrón de Observador/Observable clásico de una manera elegante:

Https://www.monterail.com/blog/2016/how-to-build-a-reactive-engine-in-javascript-part-1-observable-objects

 0
Author: David,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-06 14:30:51

Resumen:

En Javascript los objetos son colecciones de pares clave-valor. Object.defineProperty() es una función que puede definir una nueva propiedad en un objeto y puede establecer los siguientes atributos de una propiedad:

  • valor <any>: El valor asociado con la clave
  • escribible <boolean>: si writable se establece en true La propiedad se puede actualizar asignándole un nuevo valor. Si se establece en false no se puede cambiar el valor.
  • enumerable <boolean>: si enumerable se establece en la propiedad true se puede acceder a través de un bucle for..in. Además, son las únicas claves de propiedad enumerables devueltas con Object.keys()
  • configurable <boolean>: Si configurable se establece en false no puede cambiar cambiar los atributos de propiedad (valor/escribible/enumerable/configurable), también como no puede cambiar el valor no puede eliminarlo usando el operador delete.

Ejemplo:

let obj = {};


Object.defineProperty(obj, 'prop1', {
      value: 1,
      writable: false,
      enumerable: false,
      configurable: false
});   // create a new property (key=prop1, value=1)


Object.defineProperty(obj, 'prop2', {
      value: 2,
      writable: true,
      enumerable: true,
      configurable: true
});  // create a new property (key=prop2, value=2)


console.log(obj.prop1, obj.prop2); // both props exists

for(const props in obj) {
  console.log(props);
  // only logs prop2 because writable is true in prop2 and false in prop1
}


obj.prop1 = 100;
obj.prop2 = 100;
console.log(obj.prop1, obj.prop2);
// only prop2 is changed because prop2 is writable, prop1 is not


delete obj.prop1;
delete obj.prop2;

console.log(obj.prop1, obj.prop2);
// only prop2 is deleted because prop2 is configurable and prop1 is not
 0
Author: Willem van der Veen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-04 18:26:08

@Gerard Simpson

Si 'área' debe ser enumerable se puede escribir sin Objeto.Definitivamente propiedad, también.

var myObj = {
    get area() { return this.width * this.height }
};

myObj.width = 20;
myObj.height = 20;

for (var key in myObj) {
  if (myObj.hasOwnProperty(key)) {
    console.log(key + " -> " + myObj[key]);
  }
}

//area -> 400, width -> 20, height -> 20
 -1
Author: SammieFox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-11 11:22:29