17

What are get and set methods in ES6 class definition? Are they in fact prototype properties? For example:

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

Does this equal to Person.prototype.name = 'jack'? Furthermore, I've seen examples of setters which utilize the instance's prop like:

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

I don't want to do it this way; I want something like:

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

What can be done?

Atriace
  • 2,572
  • 1
  • 14
  • 27
feiyuerenhai
  • 308
  • 1
  • 3
  • 11
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get and https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set – Oleg Estekhin Jan 07 '17 at 06:53
  • What is `name` in `name = val` in your last example? I don't understand. Can you explain what you are trying to achieve? – Felix Kling Jan 07 '17 at 16:44
  • Possible duplicate of [What are getters and setters for in ECMAScript 6 classes?](https://stackoverflow.com/questions/28222276/what-are-getters-and-setters-for-in-ecmascript-6-classes) – Drenmi Oct 30 '17 at 23:33
  • They are in fact prototype properties. Try `Object.getOwnPropertyDescriptors(Person.prototype)`. – Константин Ван Jul 24 '19 at 05:51

3 Answers3

21

Yes, it can be done: Just drop the setter/getter syntax and add a property to the class during initialization instead:

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

The getter/setter syntax exists for properties that must be calculated based on other properties, like the area property from a circle of a given radius:

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

Or getting the full name of a Person object with firstName and lastName properties. You get the idea.

Tiago Marinho
  • 2,146
  • 17
  • 37
2

As per MDN , The get syntax binds an object property to a function that will be called when that property is looked up.

Here you are returning just a string 'jack' it is not binding to any property.

Interestingly console.log(Person.prototype.name) logs jack

But Person.hasOwnProperty(name) logs false

also once we create instance of Person call i.e const x = new Person();

console.log(x.name) -> this throws error, cant read property x.name because x.hasOwnProperty(name) is false

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

Rafique Ahmed
  • 117
  • 2
  • 8
1

I know this is a late response, but it doesn't look like anyone followed up on your response:

we know that class is infact a shorthand for prototype, in constructor method, we can instantilize the object. however, what i want is to define a prop in its prototype within class definition but outside the constructor method

You can just continue to declare the class as you did:

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

And then define the properties like this:

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

or whatever getters and setters you want.

I gave the actual _radius member a leading underscore to differentiate it as the member variable separate from the radius property being added, since they'd both be this.radius otherwise, leading to a stack overflow if you try to set it.

But you asked about putting the prop definitions in a separate function, and my first thought would be how to this with multiple separate instances of a Circle...

So here is a full working example with two Circle definitions, adding the props from a separate function, along with a CodePen of it here: 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}`);

Output of the above is:

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
Appurist - Paul W
  • 1,291
  • 14
  • 22