最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Purpose of getters and setters in Javascript classes - Stack Overflow

programmeradmin2浏览0评论

I have been learning how to use classes in JavaScript, and something that always confused me was the how getters and setters work. I think I now finally understand them, is the below explanation correct?
They are no different to normal methods, and simply provide an alternative syntax.
A getter is simply an alternative to a method which cannot have a parameter, and means you don't have to use () to call, e.g.:

get myGetter() { return { msg: "hello" } };
...
classInstance.myGetter.msg; // "hello"

Is equivalent to:

myGetter() { return { msg: "hello" } };
...
classInstance.myGetter().msg; // "hello"

A setter is simply an alternative for a method that does take a parameter, e.g.:

set mySetter(value) { this.value = value };
...
classInstance.mySetter = "hello";

Is equivalent to:

mySetter(value) { this.value = value };
...
classInstance.mySetter("hello");

I have been learning how to use classes in JavaScript, and something that always confused me was the how getters and setters work. I think I now finally understand them, is the below explanation correct?
They are no different to normal methods, and simply provide an alternative syntax.
A getter is simply an alternative to a method which cannot have a parameter, and means you don't have to use () to call, e.g.:

get myGetter() { return { msg: "hello" } };
...
classInstance.myGetter.msg; // "hello"

Is equivalent to:

myGetter() { return { msg: "hello" } };
...
classInstance.myGetter().msg; // "hello"

A setter is simply an alternative for a method that does take a parameter, e.g.:

set mySetter(value) { this.value = value };
...
classInstance.mySetter = "hello";

Is equivalent to:

mySetter(value) { this.value = value };
...
classInstance.mySetter("hello");
Share Improve this question asked Sep 14, 2020 at 16:34 Max888Max888 3,8104 gold badges35 silver badges76 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 5

Functionally, that explanation is mostly correct, however they also have a more semantic meaning. Getters/setters are very useful for updating things that depend on a value or calculating a value, but they shouldn't be used for triggering actions. For example, this is a wrong usage of a getter:

const alerter = new Alerter;
// [...]
alerter.alert = "Hi there!"; // Alerts "Hi there!"

This is a good one:

const player = new Player;
// [...]
player.health--; // Also updates the health bar

It's also worth noting that, while in most circumstances, they behave like methods, they aren't methods at all! They are part of properties.

In JS, properties can have data descriptors and accessor descriptors. Data descriptors are "normal" properties. They have a value and you can get/set it.

const obj = {
  prop: 1;
};

console.log(obj.prop); // Get; logs 1
obj.prop = 2; // Set

Accessor descriptors don't hold a value, and allow for setting what happens when the property is get and set.

const obj = {};
Object.defineProperty(obj, "prop", {
  get() {
    console.log("Getter was called");
    return 1;
  },
  set(v) {
    console.log("Setter was called with the value %o.", v)
  }
});

/* Alternative syntax:

class Example {
  get prop() {
    console.log("Getter was called");
    return 1;
  }
  set prop(v) {
    console.log("Setter was called with the value %o.", v)
  }
}
const obj = new Example;
*/

console.log(obj.prop); // Get; logs 1
obj.prop = 2; // Set

That code logs:

Getter was called
1
Setter was called with the value 2.

There is a huge difference between getters/setters and normal properties, in their most simple form you could think of them as an alternative syntax. however getters/setters provide more convenient solutions for certain use cases - though eventually getters/setters and methods are properties, getters/setters has accessor descriptors while methods has data descriptors.

I'm gonna list some few use cases on top of my head

  • getters/setters enable you to trigger custom functionality when reading/setting a property without having to create two different methods
let xThatShouldBeHidden = 1;
const object = { 
   get x() {
    return xThatShouldBeHidden
   },
   set x(newX) {
     if (newX === 0) {
       throw new Error('You can not set x to 0')
     }
     xThatShouldBeHidden = newX
   }      
}

Triggering custom functionality is a cool feature, it enables you to do optimizations while still abstracting that behind simple syntax. Imagine you you have array of items that has values, and later you want to get the weight of the item (value / sum of all values of items)

const items = [{val: 2}, {val:4}]
one way to do it would be which required you to loop twice even if eventually the weight was read from only one item
const totalSum = items.reduce((acc,cur), acc + cur.val,0));
const itemsWithWeights = items.map(item => ({...item, weight: item.val / totalSum});

now with getters we do it in one loop plus number of actual reads
const getItemsWithWeightsGetter = () => {
  let totalSum;

  return items.map(item => ({
    ...item,
    get weight() {
      if (totalSum === undefined) {
        totalSum = items.reduce((acc, cur) => acc + cur.val, 0);
      }
      return item.val / totalSum;
    },
  }));
};

const itemsWithWeightsGetter = getItemsWithWeightsGetter();
  • another use case is the example i just shared above, when you provide just a getter that makes the value read only, making code throws when you try to set the value - in strict mode only

The difference is, you can have a getter/setter pair with the same name. For example, when working with DOM, there is the innerHTML getter/setter pair.

const element = document.querySelector("div")

console.log(element.innerHTML) // Outputs HTML as string

element.innerHTML = "Hello!" // Sets the HTML of element to "Hello!"
发布评论

评论列表(0)

  1. 暂无评论