为什么这个可配置属性不可删除?

时间:2015-03-14 00:48:58

标签: javascript properties language-lawyer ecma262

可配置属性似乎是可删除的:

var o = {};
Object.defineProperty(o, 'prop', {
    configurable: true,
    value: 'val'
});
delete o.prop; // true
o.prop;        // undefined

但它在以下情况下不起作用,至少在Firefox和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

但这似乎与规范相矛盾。

delete运算符的定义如下:

  

11.4.1 - The delete Operator

     

制作 UnaryExpression delete UnaryExpression 是   评估如下:

     

因此使用delete的结果取决于[[删除]]。现在让我们看看[[删除]]的作用:

  

8.12.7 - [[Delete]] (P, Throw)

     

当使用属性调用 O 的[[Delete]]内部方法时   名称​​ P 和布尔标志投掷,采取以下步骤:

     
      
  • desc 成为调用 O 的[[GetOwnProperty]]内部方法的结果,其属性名称为 P
  •   
  • 如果 desc 未定义,则返回 true
  •   
  • 如果 desc 。[[Configurable]]为 true ,则   
        
    • O 中删除名为 P 的属性。
    •   
    • 返回 true
    •   
  •   
  • 如果投掷,则抛出 TypeError 例外。
  •   
  • 返回 false
  •   

因此,如果属性是可配置的,则应该是可删除的。

但是等等,也许Object.getOwnPropertyDescritor是一个巨魔,并且说属性是可配置的,但[[Configurable]]是 false 。我们来看看:

  

15.2.3.3 - Object.getOwnPropertyDescriptor ( O, P )

     

当调用 getOwnPropertyDescriptor 函数时,   采取以下步骤:

     
      
  • 如果Type O )不是Object,则抛出 TypeError 异常。
  •   
  • 名称ToString P )。
  •   
  • desc 成为使用参数 name 调用 O 的[[GetOwnProperty]]内部方法的结果。
  •   
  • 返回调用FromPropertyDescriptor desc )的结果。
  •   

所以它也使用[[GetOwnProperty]],如[[Delete]]。也许巨魔是FromPropertyDescriptor?

  

8.10.4 FromPropertyDescriptor ( Desc )

     

调用抽象操作FromPropertyDescriptor时   属性描述符 Desc ,采取以下步骤:

     
      
  • 如果 Desc 未定义,则返回 undefined
  •   
  • obj 成为创建新对象的结果,就好像通过表达式 new Object(),其中对象是标准构建的在   具有该名称的构造函数。
  •   
  • ...
  •   
  • 使用参数&#34; configurable&#34;,Property Descriptor {[[Value]]调用 obj 的[[DefineOwnProperty]]内部方法:    Desc 。[[Configurable]],[[Writable]]: true ,[[Enumerable]]: true ,[[Configurable]] : true }, false
  •   
  • 返回 obj
  •   

所以不,这不是一个巨魔。属性描述符的configurable属性设置为[[Configurable]]值。

那么,如何才能删除可配置的属性?

1 个答案:

答案 0 :(得分:5)

实际上,可配置属性是可删除的。

但是存在一个大问题:这只适用于native objects,但不适用于host objects

8.6.2 - Object Internal Properties and Methods中所述,

  

主机对象可以使用any支持这些内部属性   依赖于实现的行为,只要它与之一致   本文档中说明的特定主机对象限制。

对于那些,[[GetOwnProperty]]的行为必须不同:

  

如果属性被描述为数据属性,则可能会返回   随着时间的推移,不同的值,然后[[可写]]中的任何一个或两个   并且[[Configurable]]属性必须 true ,即使没有机制   通过其他内部方法公开更改值。

在您的示例中,form.elements是由HTML规范定义的HTMLFormControlsCollection实例,因此它是主机对象。

因此,情况是

  • 它有一个自定义[[GetOwnProperty]],表示属性'0'是可配置的,因为它的值可能会改变。
  • 它还有一个自定义[[Delete]],它不会删除属性,即使[[GetOwnProperty]]表示它是可配置的。