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

时间:2019-04-19 05:36:08

标签: javascript

我正在使用下面的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 

3 个答案:

答案 0 :(得分:76)

您应将enumerable设置为true。在Object.defineProperty中,其false默认为。根据{{​​3}}。

  

可枚举

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

  默认为false。

Non-enumerable表示该属性不会在控制台中的Object.keys()for..in循环中都不会显示

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)

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

获取所有属性(包括不可枚举的属性)MDN

let profile = {
    name: 'Barry Allen',
}

// I added a new property in the profile object.

Object.defineProperty(profile , 'age', {
    value: 23,
    writable: true,
    enumerable: false
})
for(let key in profile) console.log(key) //only name will be displayed.

console.log(Object.getOwnPropertyNames(profile)) //You will se age too

答案 1 :(得分:19)

默认情况下,您用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)

您可以在logged image中看到该属性的原因是Chrome的控制台也将向您显示不可枚举的属性-但不可枚举的属性将略显灰色

enter image description here

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

答案 2 :(得分: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)