JavaScript中Object.defineProperty()的奇怪行为


72

我在玩下面的javascript代码。了解后Object.defineProperty(),我正面临一个奇怪的问题。当我尝试在浏览器或VS代码中执行以下代码时,输​​出与预期不符,而如果我尝试对代码进行调试,则输出正确

当我调试代码并评估配置文件时,我可以name & age在对象中看到该属性,但是在输出时,它仅显示该name属性

//Code Snippet 
let profile = {
  name: 'Barry Allen',
}

// I added a new property in the profile object.
Object.defineProperty(profile, 'age', {
  value: 23,
  writable: true
})

console.log(profile)
console.log(profile.age)

现在这里的预期输出应该是

{name: "Barry Allen", age: 23}
23

但我得到的输出为。请注意,我能够访问age之后定义的属性。我不确定为什么会console.log()采用这种方式。

{name: "Barry Allen"}
23 

Answers:


82

您应该设置enumerabletrue。在Object.definePropertyfalse默认情况下。根据MDN

枚举

true当且仅当该属性显示了相应的对象的属性的枚举期间。

默认为false。

不可枚举意味着该属性不会在控制台中显示Object.keys()for..in循环显示

prototype内置类的对象的所有属性和方法都是不可枚举的。这就是您可以从实例调用它们的原因,但是它们在迭代时不会出现。

获取所有属性(包括不可枚举)Object​.get​OwnProperty​Names()


我对此一无所知,但是当我通过在浏览器中运行本地代码进行检查时,它可以完美显示(尽管明确指定enumerable为false)。
随机

@randomSoul我听不懂你的意思。
Maheer Ali

1
参见-pasteboard.co/IaOxMqB.png。我没有enumerable将true设置为true age,但是仍然显示出来。
随机

7
@randomSoul在Chrome控制台中,您应该看到无数的属性都被着色为一点透明。
yqlim

4
@randomSoul这是调试功能,而不是语言功能。如果将示例更改为使用该示例,JSON.stringify它将表现一致,并忽略非enumerable属性。
迈克·卡伦

22

默认情况下,您使用定义的属性defineProperty是不可枚举的-这意味着当您遍历它们时Object.keys(它们是代码段控制台所做的),它们将不会显示。(类似地,length数组的属性不会显示,因为它是不可枚举的。)

参见MDN

数不清的

当且仅当在枚举相应对象的属性时显示此属性时,才返回true。

默认为false。

使其可枚举:

//Code Snippet 
let profile = {
  name: 'Barry Allen',
}

// I added a new property in the profile object.
Object.defineProperty(profile, 'age', {
  value: 23,
  writable: true,
  enumerable: true
})

console.log(profile)
console.log(profile.age)

您可以在已记录的图像中看到该属性的原因是,Chrome的控制台也会向您显示不可枚举的属性-但不可枚举的属性会略显灰色

在此处输入图片说明

看看age灰色是多少,而name不是灰色-这表明它name是可枚举的,而age不是。


有人给这个pasteboard.co/IaOxMqB.pngage在chrome控制台中的showing属性。你能解释一下吗?chrome控制台的工作方式是否有所不同?
Maheer Ali

3
是的,这是Chrome控制台的行为-它会向您显示所有属性,包括不可枚举的属性,请参见编辑。不可枚举的属性(如age__proto__)将略显灰色。
某些性能

4

每当使用对象的“ .defineProperty”方法时。您最好定义描述符的所有属性。因为如果您未定义其他属性描述符,则它将假定所有属性描述符的默认值为false。因此,您的console.log检查所有可枚举的true属性,并将它们记录下来。

//Code Snippet 
let profile = {
  name: 'Barry Allen',
}

// I added a new property in the profile object.
Object.defineProperty(profile, 'age', {
  value: 23,
  writable: true,
  enumerable : true,
  configurable : true
})

console.log(profile)
console.log(profile.age)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.