1

Hey guys i am currently learning how get and set woks in javascript. Specificly talking about objects atm.

let person = {
  _name: 'Lu Xun',
  _age: 137,
  
  set age(ageIn) {
    if (typeof ageIn === 'number') {
      this._age = ageIn;
    }
    else {
      console.log('Invalid input');
      return 'Invalid input';
    }
  },
  
  get age() {
    console.log(`${this._name} is ${this._age} years old.`);
    return this._age;
  }

};


person.age = 'Thirty-nine';
person.age = 39;

console.log(person.age);

For example in this code.Why do i need a set or get , why cant i just access it like this : person.age = 59; ?Meaning why cant i just change it directly through my codesample? I Cannot grasp the concept and the need for it? could someone explain it to me thoroughly?Could someone maybe give me an easy to understand example with explanation?

itsolidude
  • 1,119
  • 3
  • 11
  • 22
  • For starters, it allows you to handle things like validation, as you've done here – user184994 Dec 20 '17 at 19:57
  • To be fair, your scenario doesn't need a getter or setter at all. But it doesn't stop you from using it. What if it wasn't age and it was something much worse to type? – Sterling Archer Dec 20 '17 at 19:57
  • Its just a beautiful way to allow [this concept](https://stackoverflow.com/questions/1568091/why-use-getters-and-setters-accessors) – Jonas Wilms Dec 20 '17 at 19:58
  • Properties are available in all advanced oo programming languages. One usage off the top of my head is for readonly properties and calculated properties. – N-ate Dec 20 '17 at 19:58
  • I still dont understand how and when to use them – itsolidude Dec 20 '17 at 20:01
  • Think about `innerHTML` DOM property. It uses its getter method when you read it, and when you set it, it runs its setter method. Just setting a string to a property wouldn't change the content of a page and trigger re-rendering. – Teemu Dec 20 '17 at 20:04

2 Answers2

1

get and set properties are called "Accessor Properties" and they differ from "Data properties" (i.e. obj.prop = value) in that they allow for logic to be implemented during the get and set operations, which is great for validation and manipulations.

If you have a Person object with an age property, would this make sense?

Person.age = "green";

Of course not, but regular "data" properties would allow it. But, with a set "accessor" property, we can disallow non-numeric and numeric data that is out of range.

var Person = {
   _age:0,
   // Accessor Property:
   get age() {
     return _age;
   },
   set age(value) {
     // Can't be non-numeric or out of range
     if (/^\d+$/.test(value) && value > 0 && value < 110) {
       this._age = value;
     }
   }
};

But, they also differ in how the set operation is handled when it comes to inherited properties.

Here's an example:

var Product = {
   // Data Properties:
   sku: 12345,
   name: "Super Widget",
   mfg: "ACME Corp.",
   retail: 9.95,
   suggestedWholesale: 14.95,
   implementationDate: new Date(2012, 06, 04).toLocaleDateString(),
   // Accessor Property:
   get markup() {
     // Return the difference between wholesale and retail price
     return (this.suggestedWholesale - this.retail).toFixed(2);
   },
   set markup(value) {
     // Markup cannot be more than 100
     if (value <= 100) {
       this.suggestedWholesale = this.retail + value;
     }
   }
};

// Make a new object that inherits from Product
var newProduct = Object.create(Product);

// When you GET a property value, the entire prototype chain is
// checked until the property is found or else you'll get undefined.
console.log(newProduct.name);
console.log(newProduct.markup);

// When you SET a property value, the property is ALWAYS used
// on the CURRENT object as an "own".  If the property being
// set matches an inherited property of the same name, the new
// "own" property hides the inherited one.
newProduct.name = "FOO";
console.log(newProduct.name);  // Successful override of inherited property
console.log(Product.name);     // Original object still has original property value

// EXCEPTION: accessor properties - With these the prototype chain is used:
newProduct.markup = 101; // Not allowed according to inherited set logic
console.log(newProduct.markup);  // Value doesn't change because inherited accessor set is used!
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
1

Objects have properties and methods. Properties are a way to describe the state the object is in, methods are ways to change that state and to let the object "behave":

 class Person {
   constructor(name){
      this.name = name; //name is a property
   }
   //And here weve got a method:
   sayHi(){
      alert(`Hi, im ${this.name}!`);
   }
 }

However while in most cases its very clear to seperate "state" and "behaviour" ( aka properties and methods) sometimes it is not. Lets imagine the person has a label sign method:

 showLabel(){
   document.body.innerHTML = this.name;
 }

Now we change the persons name e.g.:

 const person = new Person("Jake");
 person.showLabel();
 person.name = "Jack";

However, the label wont update :/, so while we renamed Jake to Jack, his label still shows Jake. Thats bad. For that, getters and setters were invented. These are methods that have the main aim to get and set a property (surprise ;)), but they also prevent glitches like the above one and they have many advantages, thats why they are used excessively in other languages. A sample setter for Person would be:

 setName(name){
   //Set
   this.name = name;
   //Prevent glitches
   this.showLabel();
 }

So instead of setting person.name directly, we now call the setter person.setName("Jack"). However now weve got an inconsistency between properties and properties one should not set but use a setter instead. To solve that inconsistency, js introduced get and set. Internally it behaves like methods, externally it still looks like a simple property:

 get name(){ return this._name }
 set name(value){
  this._name = value;
  this.showLabel();
 }

Usable as:

 const person = new Person("Jake");
 person.showLabel();
 person.name = "Jack"; //let the magic happen ;)

TLDR: get & set are basically a mixin of properties and methods to combine the advantages of both and to allow consistency.

Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • 2
    Minor point: Technically, JavaScript objects don't have methods - they only have properties. Some properties store simple primitive data and others store functions. When you invoke what we commonly call a method, what you are really doing is accessing the function that is stored in the property (as data) and then invoking it by appending `()` onto what you've just looked up. This is why we can reference functions stored in properties without invoking them. – Scott Marcus Dec 20 '17 at 20:20
  • So do i get this right? Getter and setter are used to manipulate the properties within a key for ex. `name: oli;` ? Is it bc they are private? and cant be changed outside of the object so you have to define a set or get function to change it WHICH YOU CAN ACCESS OUTSIDE OF THE OBJECT? – itsolidude Dec 20 '17 at 20:43
  • i really struggle at this – itsolidude Dec 20 '17 at 20:44
  • @itsolidude actually js has no real private properties (yet!). So its convention to mark internal properties with `_` which i did above. So its common to use a property thats exposed with getters/setters (`name`)(if you do `this.name = "whatever"` inside a method it will be called too) and an internal property (`this._name`) that keeps the properties state – Jonas Wilms Dec 20 '17 at 20:58
  • @itsolidude I think you are making too much out of this and over complicating the issue. Sometimes the value that a user wants to set for a property needs to be checked for validity, that's what a setter can do for you and sometimes a value needs to be manipulated before it's given back to you, that's what getters do. – Scott Marcus Dec 20 '17 at 21:05
  • @JonasW. so is it like a gate that changes the value when it goes through? – itsolidude Dec 20 '17 at 21:38
  • @itsolidude it could behave like this yes. However there are many other usecases – Jonas Wilms Dec 21 '17 at 06:20