Using Getters and Setters in Javascript

The Getters and Setters are known as accessor properties in JavaScript. They look like normal properties but are actually functions mapped to a Property. The Setter function runs when we assign a value to the Property. The Getter function runs when we access the Property.

Accessor Properties in JavaScript

We learned about JavaScript Properties. There are two kinds of properties in JavaScript. Data Properties & Accessor Properties.

The Data Property is mapped to a value. The value can be a primitive value, object, or function.

The accessor property is not mapped to a value but to one or two accessor functions. The accessor functions contain the logic to store or retrieve the value.

How to Create Getters & Setters

There is two way in which you can create a Getter & Setter properties in JavaScript.

  1. Object Literal
  2. DefineProperties Method

There is an older syntax, __defineGetter__ and __defineSetter__, but it’s deprecated

Using Object Literal

The following is the syntax for creating a Getter & Setter property using the object Literal syntax or object initializer.

Where
propName: is the name of the property.

get: is the method that executes when we read the value of the Property. Note that we cannot pass an argument to the getter method. The return value of the getter method becomes the value of the property access expression.

set: is the method that executes when we assign a value to the property. The JavaScript invokes the setter method with the value of the right-hand side of the assignment as the argument. If the setter method returns a value then it is ignored.

In the following example, we use color as a getter & setter property.

We use the accessor property just like we use the regular Property. For Example, we do not invoke the color property in the above example as car.color() but as car.color. The getter & setter method run behind the scene.

When we access the car.color the getter method executes and it returns the value of the _color property.

We assign the car.color="red" the setter method executes. Inside the setter method, we assign the value to the property _color.

Notice that the color accessor property behind the scene uses the _color property to store the value. _color property is the backing property of the color accessor property. We prepend the backing property with an underscore to indicate that _color should not be accessed directly.

Note that you cannot use the same name for an accessor property and a regular property.

Since ES6, you can also use the computed property names in getters & setters also. Simply enclose the expression inside square brackets( []).

Using DefineProperties

We can add a getter & setter on existing objects using the defineProperty function.

The DefinePropery not only allows us to add a new property but also allows us to set its descriptors ( known as accessor descriptors) or flags. The accessor descriptors have the following properties.

get is a function without arguments that serves as a getter for the property.

set is a function with one argument that serves as a setter for the property.

enumerable if true, then this property shows up during the enumeration of the properties. Defaults to false.

configurable if true, then we are allowed to modify the property descriptor and delete the property. Defaults to false.

Using Getters & Setters

Use getter or setter only when you need a specific functionality provided by them.

There is no need to use accessor methods if you are simply using them to get or set the data property as in the example below. Plain property access is a better option here.

But there are some of the use cases, where you can think of using the Getters & Setters.

Validating values

In the example below, we want to limit the rate field to 10, if the user assigns any rate above 10. This can be easily achieved by a setter method.

Another use case is to log the values as the property is being read or written to.

Read only /Write only Properties

The Setters & getters can be used to create read-only or write-only properties.

If the property has only a getter method, then it is a read-only property. If it has only a setter method then it is a write-only property

In the following example, we only define a get method, making the color property read-only. Setting the color property using an assignment ( car.color="red"; ) will not throw the error, but won’t do anything.

Similarly, you can create a write-only property by only defining the setter method. Any attempt to read the write-only property always returns undefined.

Perform Some logic

In the following IntCalculator, we use the setter method to check if the rate & amount differs from their previous values and calculate the interest if they differ. This helps in saving precious CPU time.

We can further optimize the above code, by running the calculation only when the user asks for interest. The code runs the calculations only if the amount & rate differs by checking the _isDirty variable.

Pitfalls

Backing Property

We use the underscore in the property names to indicate that nobody should access these variables.

In the Intcalculator example, if anyone changes the _amount or _rate directly, then our calculator will not calculate the interest correctly and fails. This is because, in JavaScript, you cannot create private property like in C# or Java.

One simple pattern to avoid such an issue is use the enclose the object in a function and use the concepts of block scope & lexical scope

In the example below, we move the car object inside the function getCar and return it. We move the private property _color outside the car object but inside the function. Due to the rules of block scope, the _color is accessible inside the car object, but not accessible outside the getCar function.

Note that when we assign green to the car._color, it creates a new property _color in the car object. This does not affect the color property as it depends on the _color property defined in the function scope.

Getter has higher precedence

You should not give the same name to a getter and a property.

This is because the getter will always take precedence

In the example below, you will never be able to access name property as the getter property name has higher precedence.

If you happen to use the name as the backing property, you will end up with a ” Maximum call stack size exceeded” error as in the example below. this.name inside the getter function resolves to itself hence creating an infinite loop

getValue / setValue pattern

You can implement functionality similar to getter & setter using the getValue / setValue pattern.

Leave a Comment

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top