When is a getter function useful in JavaScript?

Viewed 82

Specifically when used within objects, when would a getter function be used over a regular function. For example, what is the difference between using

const obj = {
        get method() {
                return data;
        }
};
console.log(obj.method);

and this

conts obj = {
        method() {
                return data;
        }
};
console.log(obj.method());
5 Answers

1 . With a normal property/method, you can change its value. A getter method cannot have its value changed. Look what happens when we try to change the getter here (it doesn't change):

const obj = {
    methodNormal() {
        return 5;
    },
    get methodGetter() {
        return 5;
    }
};

obj.methodNormal = "red";
obj.methodGetter = "blue";

console.log(obj);

2 . Secondly, with a normal property you have the luxury of either returning the function i.e. obj.methodNormal or returning the function executing i.e. obj.methodNormal(). With getter functions you do not have the luxury of returning the function. You can only do obj.methodGetter which executes that function. The code snippet below demonstrates that.

const obj = {
    methodNormal() {
        return 5;
    },
    get methodGetter() {
        return 5;
    }
};

let captureNormalMethod = obj.methodNormal;
let captureGetterMethod = obj.methodGetter;

console.log(captureNormalMethod);
console.log(captureGetterMethod);

Both these qualities - being unchangeable & unable to be captured in a new variable or property - contribute to getter functions having a sense of 'hiddenness'. Now you can understand what people mean when they say getters are 'read-only' properties!


Further reading:
What I've been referring to as 'normal properties' are called data properties (good article).
Getter methods are an example of what are called accessor properties (good article).

A method can only return data a property can also have a setter

This is useful if you want to expose read-only properties. It isn't just a function to the caller.

In your example, both do the same thing, but the importance is not how they are alike but how they are not. You can, for example, pass the method version as an argument somewhere else to do some lazy execution, but the getter won't work like that.

const obj = {
  lazyProp(parameter) {
    return parameter + 2;
  }
}

function evaluateLazy(fn) {
  return fn()
}

evaluateLazy(obj.lazyProp)

One useful scenario is where you want to use regular property access on all your properties, but need to invoke a method to calculate a given value. For example take the following example which doesn't use a getter. It ends up printing the function, not the return value of the function. Without a getter, we would need to handle a specific case where the value is a function, and then invoke it.

const obj = {
  x: 10,
  y: 20,
  total() {
    return this.x + this.y;
  }
}

const prettyPrintObj = obj => {
  for(let key in obj) {
    console.log(`${key.toUpperCase()} is ${obj[key]}`);
  }
}

prettyPrintObj(obj);

However, with a getter, we can use the same function, and don't need to handle specific cases for where obj[key] is a function, as simply doing obj[key] on a getter will invoke the function for you:

const obj = {
  x: 10,
  y: 20,
  get total() {
    return this.x + this.y;
  }
}

const prettyPrintObj = obj => {
  for(let key in obj) {
    console.log(`${key.toUpperCase()} is ${obj[key]}`);
  }
}

prettyPrintObj(obj);

Related