问题
Configurable properties seem to be deletable:
var o = {};
Object.defineProperty(o, 'prop', {
configurable: true,
value: 'val'
});
delete o.prop; // true
o.prop; // undefined
But it doesn't work in the following case, at least on Firefox and Chrome:
var form = document.createElement('form'),
input = document.createElement('input');
form.appendChild(input);
var elems = form.elements;
Object.getOwnPropertyDescriptor(form, 0)
.configurable; // true <────────────────────── !!!
delete elems[0]; // false │
elems[0]; // input │
(function(){ 'use strict'; // V
delete elems[0]; // TypeError: property 0 is non-configurable
})(); // and can't be deleted
But this seems to contradict the spec.
The delete
operator is defined like this:
11.4.1 - The delete Operator
The production UnaryExpression :
delete
UnaryExpression is evaluated as follows:
- Let ref be the result of evaluating UnaryExpression.
- [...]
- If IsPropertyReference(ref) is true, then
- Return the result of calling the [[Delete]] internal method on ToObject(GetBase(ref)) providing GetReferencedName(ref) and IsStrictReference(ref) as the arguments.
So the result of using delete
depends on [[Delete]]. Now let's see what [[Delete]] does:
8.12.7 - [[Delete]] (P, Throw)
When the [[Delete]] internal method of O is called with property name P and the Boolean flag Throw, the following steps are taken:
- Let desc be the result of calling the [[GetOwnProperty]] internal method of O with property name P.
- If desc is undefined, then return true.
- If desc.[[Configurable]] is true, then
- Remove the own property with name P from O.
- Return true.
- Else if Throw, then throw a TypeError exception.
- Return false.
Therefore, if the property is configurable, it should be deletable.
But wait, maybe Object.getOwnPropertyDescritor
is a troll and says that a property is configurable, but [[Configurable]] is false. Let's see:
15.2.3.3 - Object.getOwnPropertyDescriptor ( O, P )
When the getOwnPropertyDescriptor function is called, the following steps are taken:
- If Type(O) is not Object throw a TypeError exception.
- Let name be ToString(P).
- Let desc be the result of calling the [[GetOwnProperty]] internal method of O with argument name.
- Return the result of calling FromPropertyDescriptor(desc).
So it also uses [[GetOwnProperty]], like [[Delete]]. Maybe the troll is FromPropertyDescriptor?
8.10.4 FromPropertyDescriptor ( Desc )
When the abstract operation FromPropertyDescriptor is called with property descriptor Desc, the following steps are taken:
- If Desc is undefined, then return undefined.
- Let obj be the result of creating a new object as if by the expression new Object() where Object is the standard built-in constructor with that name.
- ...
- Call the [[DefineOwnProperty]] internal method of obj with arguments "
configurable
", Property Descriptor {[[Value]]: Desc.[[Configurable]], [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.- Return obj.
So no, it is not a troll neither. The configurable
property of the property descriptor is set to the [[Configurable]] value.
How is it possible, then, that a configurable property can't be deleted?
回答1:
Effectively, configurable properties are deletable.
But there is a big problem: that only applies to native objects, but not to host objects.
As explained in 8.6.2 - Object Internal Properties and Methods,
Host objects may support these internal properties with any implementation-dependent behaviour as long as it is consistent with the specific host object restrictions stated in this document.
For those, [[GetOwnProperty]] must behave differently:
If a property is described as a data property and it may return different values over time, then either or both of the [[Writable]] and [[Configurable]] attributes must be true even if no mechanism to change the value is exposed via the other internal methods.
In your example, form.elements is a HTMLFormControlsCollection instance defined by the HTML spec, so it's a host object.
Therefore, the situation is
- It has a custom [[GetOwnProperty]] which says that the property
'0'
is configurable because its value may change. - It also has a custom [[Delete]] which doesn't delete the property, even if [[GetOwnProperty]] says it's configurable.
来源:https://stackoverflow.com/questions/29044212/why-is-this-configurable-property-not-deletable