简体   繁体   English

为什么我的属性在装饰器中的 Object.defineProperty 之后消失了?

[英]Why does my property disapear after Object.defineProperty in decorator?

I have a decorator that casts a string number to a javascript number.我有一个装饰器,可以将字符串数字转换为 javascript 数字。

Example: "87" -> 87 .示例: "87" -> 87

The code is quite simple:代码非常简单:

function digit(target: any, key: string) {

  // property value
  var _val = this[key];

  // property getter
  var getter = () =>  _val;

  // property setter
  var setter = (newVal) => _val = parseInt(newVal)

  // Create new property with getter and setter
  Object.defineProperty(target, key, {
    get: getter,
    set: setter,
    enumerable: true,
    configurable: true,
  });
}

class User {

  @digit
  public id: number;
  public isActive: boolean;

  constructor(instanceData) {
    this.id = instanceData.id;
    this.isActive = instanceData.isActive;
  }
}

let user = new User({
  id: '712',
  isActive: '1'
})

console.log([user.id]) // [ 712 ] as expected
console.log(user) // Person { isActive: '1' }

Why doesn't the id field appear in the second console.log and how can I make it appear ?为什么 id 字段没有出现在第二个 console.log 中,我该如何让它出现? I can access it but it's hidden in the console.我可以访问它,但它隐藏在控制台中。

Thanks !谢谢 !

Because a property decorator for an instance property is applied to the prototype of the class, not to any instance .因为实例属性的属性装饰器应用于类的原型,而不是任何实例 That is the best you can do because no instance of User exists before you call new User() .这是您能做的最好的事情,因为在您调用new User()之前不存在User实例。 When you just use console.log() to get debug output you only see the instance's own properties, not the ones on the prototype.当您只使用console.log()获取调试输出时,您只能看到实例自己的属性,而不是原型上的属性。

Since all instances share a prototype, you probably don't want to do it this way:由于所有实例共享一个原型,您可能不想这样做:

let user = new User({
  id: '712',
  isActive: '1'
}) 
let user2 = new User({
  id: '567',
  isActive: '1'
})
console.log(user.id) // 567!

One prototype, one id value for the whole class.一个原型,一个用于整个类的id值。 All User objects have the same id .所有User对象都具有相同的id Oops.哎呀。


You probably want to at least do something to instances when they are available:您可能希望至少在实例可用时对其做一些事情:

function digit(target: any, key: string) {
  // Create new property with getter and setter
  Object.defineProperty(target, key, {
    get: function () { return this._val },
    set: function (newVal) { this._val = parseInt(newVal) },
    enumerable: true,
    configurable: true,
  });
}

Notice the use of this inside the get and set methods.请注意在getset方法中使用this That puts the _val property on the instance, so you'll get distinct ones.这会将_val属性放在实例上,因此您将获得不同的属性。 You will still not see id via console.log() , (and you will see _val ).您仍然不会通过console.log()看到id (并且您看到_val )。


There are too many ways to configure the object so that it prints out what you expect with console.log() and behaves the way you expect (one id per instance) for me to enumerate here.有太多方法可以配置对象,以便它用console.log()打印出您期望的内容,并按照您期望的方式运行(每个实例一个id ),供我在此处枚举。 As one hint: you could put the property accessor on the instance by modifying the class constructor instead of trying to use a decorator.作为一个提示:您可以通过修改类构造函数而不是尝试使用装饰器来将属性访问器放在实例上。 And make sure the added _val is not enumerable so it does not appear.并确保添加的_val不可枚举,因此它不会出现。 Hope that helps;希望有所帮助; good luck!祝你好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM