web-dev-qa-db-ja.com

ES6クラスのゲッターとセッターは実際には何ですか?

eS6クラス定義の実際のゲッターメソッドとセッターメソッドとは彼らは実際のプロトタイプ小道具ですか?たとえば:

class Person{
  constructor(){};
  get name(){
    return 'jack';
  }
  set name(){
    // ???
  }
}

これはPerson.prototype.name = 'jack'と同じですか。

そして別の質問、私はインスタンスのプロップを利用するセッターの例を見ました:

class Person{
  constructor(){
    this._name = 'jack';
  };
  get name(){
    return this._name;
  }
  set name(val){
    this._name = val;
  }
}

私はこのようにしたくないので、次のようなものが必要です:

class Person{
  constructor(){};
  get name(){
    return 'jack';
  }
  set name(val){
    // like this
    // name = val;
  }
}

何ができるでしょうか?

14
feiyuerenhai

はい、できます。代わりに、setter/getter構文を削除し、初期化中にクラスにプロパティを追加するだけです。

class Person{
    constructor(name){
        this.name = name;
    }
}

特定のareaの円のradiusプロパティなど、他のプロパティに基づいて計算する必要があるプロパティには、getter/setter構文が存在します。

class Circle {
    constructor (radius) {
        this.radius = radius;
    }
    get area () {
        return Math.PI * this.radius * this.radius;
    }
    set area (n) {
        this.radius = Math.sqrt(n / Math.PI);
    }
}

または、PersonおよびfirstNameプロパティを持つlastNameオブジェクトの完全な名前を取得します。あなたはアイデアを得ます。

20
Tiago Marinho

MDNに従って、get構文はオブジェクトプロパティを、そのプロパティが検索されたときに呼び出される関数にバインドします。

ここでは、どのプロパティにもバインドされていない文字列「jack」のみを返しています。

興味深いことに、console.log(Person.prototype.name)ログジャック

しかし、Person.hasOwnProperty(name)はfalseを記録します

また、Person呼び出しのインスタンスを作成したら、つまりconst x = new Person();

console.log(x.name)->これはエラーをスローし、x.hasOwnProperty(name)がfalseであるため、プロパティx.nameを読み取ることができません

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get

2
Rafique Ahmed

私はこれが遅い応答であることを知っていますが、あなたの応答をフォローアップしている人はいないようです:

クラスはプロトタイプの省略形であり、コンストラクターメソッドではオブジェクトをインスタンス化できることがわかります。しかし、私が欲しいのは、クラス定義内でプロトタイプのプロップを定義することですが、コンストラクターメソッドの外側です。

あなたはあなたがしたようにクラスを宣言し続けることができます:

class Circle {
    constructor (radius) {
        this._radius = radius;
    }
}

そして、次のようにプロパティを定義します。

Object.defineProperties(obj, {
    radius: {
        get: function () {
          return this._radius;
        },
        set: function (n) {
            this._radius = n;
        }
    },
    area: {
        get: function () {
          return Math.PI * this._radius * this._radius;
        },
        set: function (n) {
            this._radius = Math.sqrt(n / Math.PI);
        }
    }
});

またはあなたが望むどんなゲッターとセッターでも。

actual_radiusメンバーは、追加されるradiusプロパティとは別のメンバー変数として区別するための先行アンダースコアです。両方ともthis.radiusになるため、設定しようとするとスタックオーバーフローが発生します。

しかし、小道具の定義を別の関数に入れることについて質問しました。私の最初の考えは、Circleの複数の個別のインスタンスでこれを行う方法です...

したがって、2つのCircle定義を使用した完全に機能する例を以下に示します。別の関数からの小道具と、そのCodePenを追加します。 https://codepen.io/appurist/pen/ZEbOdeB?editors=0011

class Circle {
  constructor(r) {
    this._radius = r;
    addProps(this);
  }
}

function addProps(obj) {
  Object.defineProperties(obj, {
    radius: {
      get: function () {
        return this._radius;
      },
      set: function (n) {
        this._radius = n;
      }
    },
    area: {
      get: function () {
        return Math.PI * this._radius * this._radius;
      },
      set: function (n) {
        this._radius = Math.sqrt(n / Math.PI);
      }
    }
  });
}

let circle = new Circle(7);
let circle2 = new Circle(2);

console.log(`circle radius and area are: ${circle.radius} ${circle.area}`);
circle.radius = 4;
console.log(`circle radius and area now: ${circle.radius} ${circle.area}`);
circle.area = 78.53981633974483;
console.log(`circle radius and area now: ${circle.radius} ${circle.area}`);

console.log(`circle2 radius and area are: ${circle2.radius} ${circle2.area}`);
circle2.radius = 3;
console.log(`circle2 radius and area now: ${circle2.radius} ${circle2.area}`);
circle2.area = 50.26548245743669;
console.log(`circle2 radius and area now: ${circle2.radius} ${circle2.area}`);

上記の出力は次のとおりです。

circle radius and area are: 7 153.93804002589985
circle radius and area now: 4 50.26548245743669
circle radius and area now: 5 78.53981633974483

circle2 radius and area are: 2 12.566370614359172
circle2 radius and area now: 3 28.274333882308138
circle2 radius and area now: 4 50.26548245743669
0