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

Rav*_*are 70 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)
Run Code Online (Sandbox Code Playgroud)

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

{name: "Barry Allen", age: 23}
23
Run Code Online (Sandbox Code Playgroud)

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

{name: "Barry Allen"}
23 
Run Code Online (Sandbox Code Playgroud)

Mah*_*Ali 77

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

枚举

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

默认为false。

不可枚举意味着该属性将不会在控制台中显示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)
Run Code Online (Sandbox Code Playgroud)

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

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

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
Run Code Online (Sandbox Code Playgroud)

  • @randomSoul在Chrome控制台中,您应该看到无数的属性颜色有点透明。 (7认同)
  • @randomSoul这是调试功能,而不是语言功能。如果您将示例更改为使用JSON.stringify,则它将保持一致,并忽略非enumerable属性。 (3认同)

Cer*_*nce 20

默认情况下,您使用定义的属性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)
Run Code Online (Sandbox Code Playgroud)

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

在此处输入图片说明

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

  • 是的,这是Chrome控制台的行为-它会向您显示*所有*属性,包括不可枚举的属性,请参见编辑。不可枚举的属性(例如`age`和`__proto__`)将略显灰色。 (3认同)

小智 5

每当您使用对象的“.defineProperty”方法时。您应该更好地定义描述符的所有属性。因为如果您没有定义其他属性描述符,那么它会假定所有属性描述符的默认值都是错误的。因此,您的 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)
Run Code Online (Sandbox Code Playgroud)