ウェブサイト検索

javascript - デコレーターで Object.defineProperty を使った後、なぜ私のプロパティが消えるのですか?


私は文字列の数字をJavaScriptの数字に変換するデコレーターを持っています。

例: "87" -> 87.

コードは非常に簡単です:

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' }

なぜ2番目のconsole.logにはidフィールドが表示されないのですか、そしてそれを表示させるにはどうすればいいですか?アクセスはできますが、コンソールでは隠れています。

ありがとう!

回答 #1

インスタンスプロパティのためのプロパティデコレーターは、クラスのインスタンスではなくプロトタイプに適用されるためです。new User()を呼び出す前にはUserのインスタンスは存在しないので、それができる限界です。console.log()を使ってデバッグ出力を取得する場合、インスタンス自身のプロパティしか見えず、プロトタイプ上のプロパティは見えません。

すべてのインスタンスがプロトタイプを共有しているので、おそらく次のような方法で行いたくないでしょう:

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

1つのプロトタイプ、クラス全体で1つのid値。すべてのUserオブジェクトが同じidを持つ。おっと。

おそらく、インスタンスが利用可能なときには少なくとも何かをしたいでしょう:

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,
  });
}

get と set メソッドの内部で this を使用していることに注意してください。これにより _val プロパティがインスタンス上に置かれるため、それぞれ異なるものを取得できます。console.log() では id は表示されませんが、_val は表示されます。

オブジェクトを構成して、console.log() で期待通りに出力し、かつ期待通りの動作(一インスタンスにつき一つの id)をさせる方法はあまりにも多すぎて、ここで全部列挙することはできません。一つのヒントとしては、デコレーターを使おうとする代わりに、クラスのコンストラクターを変更してインスタンスにプロパティアクセサを置くという方法があります。そして、追加する _val が列挙可能になっていないことを確認し、表示されないようにしてください。参考になれば幸いです。頑張ってください!