feiyuerenhai
feiyuerenhai

Reputation: 300

What are ES6 class getter and setter actually?

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?

Upvotes: 16

Views: 32540

Answers (3)

Appurist - Paul W
Appurist - Paul W

Reputation: 1458

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

Upvotes: 1

Tiago Marinho
Tiago Marinho

Reputation: 2216

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.

Upvotes: 20

Rafique Ahmed
Rafique Ahmed

Reputation: 117

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

Upvotes: 2

Related Questions