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

Ori*_*iol 7 javascript properties ecma262 language-lawyer

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

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

但它在以下情况下不起作用,至少在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
Run Code Online (Sandbox Code Playgroud)

但这似乎与规范相矛盾.

delete运营商的定义是这样的:

11.4.1 - 删除操作员

生产UnaryExpression:delete UnaryExpression的计算方法如下:

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

8.12.7 - [[删除]](P,投掷)

当使用属性名P和布尔标志Throw调用O的[[Delete]]内部方法时,将执行以下步骤:

  • desc是调用属性名为PO的[[GetOwnProperty]]内部方法的结果.
  • 如果递减不确定的,则返回.
  • 如果desc.[[Configurable]]为,那么
    • O中删除名为P的属性.
    • 回归真实.
  • 否则,如果抛出,则抛出TypeError异常.
  • 返回false.

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

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

15.2.3.3 - Object.getOwnPropertyDescriptor(O,P)

getOwnPropertyDescriptor函数被调用时,都采取了以下措施:

  • 如果Type(O)不是Object则抛出TypeError异常.
  • 我们的名字的ToString(P).
  • desc是使用参数名称调用O的[[GetOwnProperty]]内部方法的结果.
  • 返回调用FromPropertyDescriptor(desc)的结果.

因此它也使用[[GetOwnProperty]],如[[Delete]].也许巨魔是FromPropertyDescriptor?

8.10.4 FromPropertyDescriptor(Desc)

使用属性描述符Desc调用抽象操作FromPropertyDescriptor时,将执行以下步骤:

  • 如果说明不确定的,则返回不确定的.
  • obj是创建一个新对象的结果,好像是通过表达式new Object(),其中Object是具有该名称的标准内置构造函数.
  • ...
  • 使用参数" " 调用obj的[[DefineOwnProperty]]内部方法configurable,Property Descriptor {[[Value]]: Desc.[[Configurable]],[[Writable]]:true,[[Enumerable]]:true,[ [Configurable]]:true }和false.
  • 返回obj.

所以不,它不是一个巨魔.的configurable所述属性描述符的属性被设置为[[配置]]值.

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

Ori*_*iol 5

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

但这是一个大问题:仅适用于本机对象,不适用于宿主对象

8.6.2-对象内部属性和方法中所述

主机对象可以通过任何与实现有关的行为来支持这些内部属性,只要它与本文档中所述的特定主机对象限制一致即可。

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

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

在您的示例中,form.elementsHTMLFormControlsCollectionHTML规范定义的实例,因此它是宿主对象。

因此,情况是

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