web-dev-qa-db-ja.com

ES6クラスコンストラクターからES6プロキシを返す

ユーザーに特定のプロパティのみをオブジェクトに設定させたいのですが、同時にそのオブジェクトはカスタムクラスから構築する必要があります。

例えば

var row = new Row({
  name : 'John Doe',
  email : '[email protected]'
}, Schema);

rowはメソッドを持つことができます。しかし、ユーザーがrow.password、それらは許可されていません。

それを行う1つの方法は、new Proxy の代わりに new Rowですが、Rowクラスの内部で行っているすべてのクールな処理は失われます。が欲しいです new Rowは、プロキシのターゲットとしてthis参照を持つプロキシオブジェクトを返します。

誰かこれについて何かアイデアはありますか? mongooseを知っているなら、どのようにmongooseがやっているのですか?

17
Uday Hiwarale

プロキシが確実に発生する場合、設定機能を制限する1つの可能な解決策は、ES6プロキシインスタンスを返すことです。

デフォルトでは、JavaScriptのコンストラクタはthisオブジェクトを自動的に返しますが、thisをターゲットとしてプロキシをインスタンス化することで、カスタム動作を定義して返すことができます。プロキシのsetメソッドはブール値を返す必要があることに注意してください。

[〜#〜] mdn [〜#〜] :setメソッドはブール値を返す必要があります。割り当てが成功したことを示すには、trueを返します。 setメソッドがfalseを返し、割り当てがストリクトモードコードで発生した場合、TypeErrorがスローされます。

class Row {
  constructor(entry) {
    // some stuff

    return new Proxy(this, {
      set(target, name, value) {
        let setables = ['name', 'email'];
        if (!setables.includes(name)) {
          throw new Error(`Cannot set the ${name} property`);
        } else {
          target[name] = value;
          return true;
        }
      }
    });
  }

  get name() {
    return this._name;
  }
  set name(name) {
    this._name = name.trim();
  }
  get email() {
    return this._email;
  }
  set email(email) {
    this._email = email.trim();
  }
}

そのため、プロキシに従って設定不可能なプロパティを設定することはできません。

let row = new Row({
  name : 'John Doe',
  email : '[email protected]'
});

row.password = 'blahblahblah'; // Error: Cannot set the password property

Getメソッドでカスタム動作を設定することも可能です。

ただし、呼び出しコンテキストに返される参照を上書きすることに注意して注意してください。

注:サンプルコードはNode v8.1.3および最新のブラウザ。

22
Vahid Hallaji

プロキシをまったく使用せずにこれを行うことができます。

クラスコンストラクターでは、次のようにパスワードプロパティを定義できます。

_constructor(options, schema) {
    this.name = options.name;
    this.email = options.email;
    Object.defineProperty(this, 'password', {
        configurable: false, // no re-configuring this.password
        enumerable: true, // this.password should show up in Object.keys(this)
        value: options.password, // set the value to options.password
        writable: false // no changing the value with this.password = ...
    });
    // whatever else you want to do with the Schema
}
_

これを使用する方法の詳細については、MDNの Object.defineProperty() ページを参照してください。

12
Joshua Skrzypek