javascript - que - object defineproperty polyfill
¿Cómo deshago una llamada Object.defineProperty? (1)
var Assertion = function() {
return { "dummy": "data" };
}
Object.defineProperty(Object.prototype, ''should'', {
set: function(){},
get: function(){
return new Assertion(this);
}
});
// Insert magic here.
// This needs to be false
console.log(({}).should === undefined);
¿Qué opciones tengo en ES5 para deshacer una llamada defineProperty
?
No hay sugerencias tontas como Object.defineProperty = function() { }
por favor.
El siguiente Object.defineProperty(Object.prototype, ''should'', {})
y Object.defineProperty(Object.prototype, ''should'', { value: undefined })
Emite un Uncaught TypeError: Cannot redefine property: defineProperty
en V8
Object.defineProperty(Object.prototype, ''should'', {
set: function() {},
get: function() { return undefined; }
});
Lanza el mismo error
delete Object.prototype.should
tampoco funciona
En general, no puede deshacer una llamada defineProperty
, ya que no hay una pila de deshacer o algo así. El motor JS no realiza un seguimiento de los descriptores de atributos anteriores.
Por ejemplo,
Object.defineProperty(Object.prototype, ''foo'', {
configurable: true,
value: 1,
enumerable: false
});
Object.defineProperty(Object.prototype, ''foo'', {
get: function () {
alert(''You cannot revert me'');
return 2;
},
enumerable: true
});
Lo que puede hacer es eliminar o reconfigurar un atributo, o sobrescribir su valor. Como se mencionó en la otra respuesta, se requiere que el indicador configurable
sea true
si desea eliminar o reconfigurar. Una vez que una propiedad se define con configurable:false
, no puede cambiar el indicador configurable
.
Para eliminar un atributo (esto es supuestamente lo que quieres hacer), usa delete
:
Object.defineProperty(Object.prototype, ''foo'', {
configurable: true, // defaults to false
writable: false,
value: 1
});
delete Object.prototype.foo;
console.log(Object.prototype.hasOwnProperty(''foo'')); // false
Para reconfigurar, use defineProperty
nuevamente y pase un descriptor diferente:
Object.defineProperty(Object.prototype, ''foo'', {
configurable: true,
get: ...
set: ...
});
Object.defineProperty(Object.prototype, ''foo'', {
value: undefined
});
console.log({}.foo); // undefined
console.log(Object.prototype.hasOwnProperty(''foo'')); // true
Como se muestra en este ejemplo, puede usar defineProperty
para cambiar entre las defineProperty
de acceso ( get
/ set
) y datos ( value
).
Para sobrescribir, usa la tarea simple. En este caso, necesita que la writable
sea true
. Obviamente, esto no funciona con las propiedades de acceso. Incluso arroja una excepción:
Object.defineProperty(Object.prototype, ''foo'', {
configurable: true,
value: 1,
writable: true // defaults to false
});
Object.prototype.foo = undefined;
console.log(Object.prototype.foo); // undefined
console.log(Object.prototype.hasOwnProperty(''foo'')); // true
Object.defineProperty(Object.prototype, ''foo'', {
get: function () {
return 1;
},
writable: true // JS error!
});
Tenga en cuenta que el valor predeterminado de writable
es false
cuando usa defineProperty
, pero true
cuando usa la sintaxis simple o.attr = val;
Para definir una propiedad (previamente no existente).