为什么我不能在Javascript对象中重新定义属性?

时间:2014-08-27 02:22:55

标签: javascript

我正在使用Object.create创建一个对象,我想为其添加属性。

> var o = Object.create({});
undefined

> Object.defineProperty(o, "foo", {value: 43, enumerable: true});
{foo: 43}

> o
{foo: 43}

> o.foo
43

> for (var i in o) { console.log(i); }
foo

> Object.keys(o)
['foo']

> Object.defineProperty(o, "foo", {value: 43, enumerable: false });
TypeError: Cannot redefine property: bar

Q1)为什么我不能重新定义财产?

> o.__proto__
{}

> o.prototype
undefined

Q2)为什么原型是空的?为什么这两个值不同,即{} vs undefined

4 个答案:

答案 0 :(得分:43)

您无法重新定义该属性,因为Object.defineProperty()默认为不可配置的属性,来自docs

  

配置

     

当且仅当可以更改此属性描述符的类型并且可以从相应对象中删除属性时,才返回true。       默认为false。

因此默认为false - 您需要将其传递给configurable: true以允许它。

答案 1 :(得分:29)

  1. 默认情况下,Object.defineProperty()定义的属性为non-configurable

    要允许重新定义或重新配置它们,必须使用此属性设置为true来定义它们。

    var o = Object.create({});
    
    Object.defineProperty(o, "foo", {
        value: 42,
        enumerable: true,
        configurable: true
    });
    
    console.log(o); // { foo: 42 }
    
    Object.defineProperty(o, "foo", {
        value: 45,
        enumerable: true,
        configurable: true
    });
    
    console.log(o); // { foo: 45 }
    

  2. o.prototypeundefined,因为对象通常不具有prototype属性。

    这些属性可以在构造函数function上找到new个实例继承,大致相当于:

    function Foo() {}
    
    //  ... = new Foo();
    var bar = Object.create(Foo.prototype);
    Foo.call(bar);
    
    然而,

    对象知道它们的原型对象。它们是通过internal [[Prototype]] property引用的,__proto__是非正式的获取者/设置者:

    console.log(o.__proto__); // {}
    

    阅读[[Prototype]]的标准化方法是使用Object.getPrototypeOf()

    console.log(Object.getPrototypeOf(o)); // {}
    

答案 2 :(得分:1)

仅当可写可配置均为假时,才会发生“无法重新定义属性”。

如果可写可配置为真,错误将消失。

"use strict"

var obj = {};

Object.defineProperty(obj, "name",
{
   value: "Fundebug",
   writable: false,
   configurable: false
})

Object.defineProperty(obj, "name",
{
   value: "云麒"
}) // “Uncaught TypeError: Cannot redefine property: name”

因此,jdphenix和Jonathan并不完全正确。

答案 3 :(得分:0)

Object.defineProperty(o, "foo", {value: 43, enumerable: true});

此行定义对象foo的属性o,值:43,以及属性enumerable:truewritable:falseconfigurable:false。如果属性存在,则defineProperty更新其标志。否则,它将使用给定的值和标志创建属性;在这种情况下,如果未提供标志,则将其假定为 false

因此,这里我们将属性设为不可配置,因为configurable标志(或属性)为 false

  

制造物业non-configurable是一条单向路。我们不能改变   并以defineProperty返回。

     

准确地说,不可配置性对   defineProperty:

  • 无法更改可配置标志。
  • 无法更改可枚举标志。
  • 无法更改可写:从false更改为true(反之亦然)。
  • 无法更改访问者属性的获取/设置(但如果没有,则可以分配它们)。

因此请谨慎使用configurable中的defineProperty标志,如果要更改 enumerable writable 属性,请务必在defineProperty中将其设置为true (或标志)。 一旦设置了可配置的false,就无法将其设置为true。