使用 Object.create 时无法枚举属性

Cannot enum properties when using Object.create

本文关键字:枚举 属性 Object create 使用      更新时间:2023-09-26

我有一个像这样的对象

var Profile = Object.create(null);
Object.defineProperties(Profile, {
    id: {
        value: "",
        enumerable: true
    },
    name: {
        value: "",
        enumerable: true
    },
    active: {
        value: true,
        enumerable: true
    }
});

现在我想创建一个配置文件实例并为其提供 id 和名称,并保持活动默认值为 true,所以我这样做:

var p1 = Object.create(Profile, {
    id: {
        value: "123",
        enumerable: true
    },
    name: {
        value: "hello world",
        enumerable: true
    }
});

然后我得到了一个名为 p1 的对象,但我在

Object.getOwnPropertyNames(p1);

我也不能使用 JSON.stringify(p1) 来序列化属性"active",但我需要属性"active"可以序列化。

这是我使用 Object.create 的错误方式吗?我只想创建一个可序列化的"类"并获取它的可序列化"实例"。我该怎么做?

由于您使用了Object.create,您并没有真正将任何内容克隆/复制到生成的对象中(您调用p1)。首先,您必须了解JS在访问对象属性时如何解析它们:

J [     p1.active     ]<=========================================================' '
S p1[active] ==> JS checks instance for property divide                           | |
O  /' ||                                                                          | |
N  || || --> property found @instance? return value-------------------------------| |
=  || ||                                                                          | |
   || ===========> p1.prototype is found: Profile, check that object              | |
N  ||      ||                                                                     | |
O  ||      ||--> Profile.active found @Profile instance, return-------------------| |
T  ||      ||                                                                     | |
   ||      ==========> Profile.prototype.active (== Object.prototype.active)      | |
J  ||          ||                                                                 | |
S  ||          ||--> property found @Object.prototype, return---------------------|_|
O  ||          ||                                                                 |=|
N  ||          =======>prototype is null, return "undefined.active"~~~~~~~~~~~~~~~|X|
   ||                                                                             ' /
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~< TypeError can't read property 'x' of undefined

这基本上是可能发生的情况。现在调用JSON.stringify(p1),JS将只转向p1对象,并处理其属性(@instance级别定义的属性)。p1对象不知道Profile 上定义了 active 属性
JSON.stringify只检查我用JSON标记的步骤(第一个周期),所有其他检查(原型链)对JSON都不感兴趣。9/10,反正这只是Object.prototype,你不想把它串起来,现在好吗?

老实说,对于您(似乎)想要完成的事情,最简单的解决方案是:

p1 = JSON.parse(JSON.stringify(Profile));
p1.id = 123;
p1.name = 'hello world';
console.log(JSON.stringify(p1));//will show active property!

查看我上一条评论中的链接,以获取有关此事的更多详细信息

从 getOwnPropertyNames 上的 MDN 页面:

返回直接找到的所有属性(可枚举或不可枚举)的数组 在给定对象上。

活动属性位于 p1 的原型对象上,而不是 p1 上。

您可以使用 for in 构造迭代 p1 的所有属性(包括原型链上的属性)。要创建平面对象,您可以执行以下操作:

for (var key in obj) {
  if (!obj.hasOwnProperty(key)) {
    obj[key] = obj[key];
  }
}

Object.getOwnPropertyNames :https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames

for in :https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in

Object.create :https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create