繁体   English   中英

为什么我不能重新定义 Javascript object 中的属性?

[英]Why can't I redefine a property in a Javascript object?

我正在使用Object.create创建一个 object,我想向它添加属性。

> 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)为什么原型是空的? 为什么这两个值不同,即{}undefined

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

可配置

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

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

  1. 默认情况下,通过Object.defineProperty()定义的属性是不可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.prototype undefined因为对象通常没有prototype属性。

    这样的属性可以在构造function上找到以供new实例继承,大致相当于:

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

    然而,对象知道它们的原型对象。 它们是通过内部[[Prototype]]属性引用的,其中__proto__是/曾经是以下的非官方 getter/setter:

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

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

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

只有当writableconfigure都为 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”

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

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

这一行定义了对象o上的属性foo ,其值为:43 和属性enumerable:truewritable:falseconfigurable:false 如果该属性存在,则defineProperty更新其标志。 否则,它会创建具有给定值和标志的属性; 在这种情况下,如果未提供标志,则假定为false

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

使属性non-configurable是一条单向之路。 我们不能用defineProperty把它改回来。

准确地说,不可配置性对defineProperty施加了几个限制:

  • 无法更改可配置标志。
  • 无法更改可枚举标志。
  • 无法将 writable: false 更改为 true (反之亦然)。
  • 无法更改访问器属性的获取/设置(但可以在不存在的情况下分配它们)。

所以要小心definePropertyconfigurable标志,如果要更改可枚举可写属性(或标志),请始终在defineProperty中将其设置为true。 一旦您设置了可配置的 false,您就无法将其设置为 true。

一个可能的原因可能是您的版本问题。 Node 10 不允许实时绑定,但较新的版本现在允许这样做。 请检查您是否在节点 12 或以上。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM