【问题标题】:Strange behavior of Object.defineProperty() in JavaScriptJavaScript 中 Object.defineProperty() 的奇怪行为
【发布时间】:2019-04-19 05:36:07
【问题描述】:

我在玩下面的 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 

【问题讨论】:

    标签: javascript


    【解决方案1】:

    您应该将enumerable 设置为true。在Object.defineProperty 中默认为false。根据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)

    内置类的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

    【讨论】:

    • 我不知道这一点,但是当我通过在浏览器中运行本地代码进行检查时,它完美显示(尽管将enumerable 明确指定为false)。
    • @randomSoul 我不明白你的意思。
    • 见 - pasteboard.co/IaOxMqB.png 。对于age,我没有将enumerable 设置为true,但它仍然显示。
    • @randomSoul 在 Chrome 控制台中,您应该会看到不可枚举的属性颜色有点透明。
    • @randomSoul 这是调试功能,不是语言功能。如果您将示例更改为使用JSON.stringify,它将表现一致,并省略非enumerable 属性。
    【解决方案2】:

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

    MDN:

    可枚举

    当且仅当此属性在枚举相应对象的属性期间出现时才为真。

    默认为 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 的控制台也会向您显示不可枚举的属性 - 但不可枚举的属性将略微变灰

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

    【讨论】:

    • 有人给这个pasteboard.co/IaOxMqB.png它在chrome控制台中显示age属性。你能解释一下吗? chrome 控制台的工作方式是否不同?
    • 是的,这是 Chrome 控制台的行为 - 它会向您显示 所有 属性,包括不可枚举的属性,请参阅编辑。不可枚举的属性(如age__proto__)将略微变灰。
    【解决方案3】:

    每当您使用对象的“.defineProperty”方法时。您应该更好地定义描述符的所有属性。因为如果您不定义其他属性描述符,那么它会假定所有这些属性的默认值都是错误的。因此,您的 console.log 会检查所有 enumerable : 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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-20
      • 2011-07-28
      • 2012-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多