为什么可以';我是否重新定义Javascript对象中的属性?

为什么可以';我是否重新定义Javascript对象中的属性?,javascript,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.k

我正在使用
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
问题1)为什么我不能重新定义属性

> o.__proto__
{}

> o.prototype
undefined

问题2)为什么原型是空的?为什么这两个值不同,即
{}
未定义的

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

可配置

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

所以这默认为false-您需要传递它
configurable:true
才能允许它

  • 默认情况下,通过定义的属性为

    要允许重新定义或重新配置它们,必须将此属性设置为
    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 }
    

  • o.prototype
    未定义,因为对象通常不具有
    prototype
    属性

    这些属性可在构造函数
    函数
    s中找到,用于继承
    新的
    实例,大致相当于:

    function Foo() {}
    
    //  ... = new Foo();
    var bar = Object.create(Foo.prototype);
    Foo.call(bar);
    
    然而,对象知道它们的原型对象。它们通过一个
    \uuuuu proto\uuuuu
    被引用,这个
    \uuuuuuuu proto\uuuuuuuu>是/曾经是一个非官方的获取/设置者:

    console.log(o.__proto__); // {}
    
    阅读
    [[Prototype]]
    的标准化方法是:


  • 只有当可写可配置都为false时,“无法重新定义属性”才会发生

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

    "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”
    
    因此,jdpenix和Jonathan并不完全正确

    Object.defineProperty(o, "foo", {value: 43, enumerable: true});
    
    此行定义对象
    o
    上的属性
    foo
    ,值为43,属性
    可枚举:true
    可写:false
    可配置:false
    。如果属性存在,
    defineProperty
    更新其标志。否则,它将创建具有给定值和标志的属性;在这种情况下,如果未提供标志,则假定为false

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

    使属性
    不可配置
    是一条单行道。我们不能改变 用
    defineProperty
    返回

    准确地说,不可配置性对 定义属性:

    • 无法更改可配置标志
    • 无法更改可枚举标志
    • 无法将writable:false更改为true(反之亦然)
    • 无法更改访问器属性的get/set(但如果不存在,可以分配它们)
    因此,请注意
    defineProperty
    中的
    configurable
    标志,如果要更改可枚举和可写属性(或标志),请始终在defineProperty中将其设置为true一旦设置为false,您就无法将其设置为true。

    请小心。ES6可能会被选择所淹没…
    Object.defineProperty(o, "foo", {value: 43, enumerable: true});