W3docs

JavaScript Getters and Setters

Learn JavaScript property getters and setters: the get/set syntax, accessor vs data properties, validation, computed properties, and use in classes.

Most object properties in JavaScript are data properties — they simply store a value. But objects also support accessor properties: properties backed by functions that run whenever the property is read or written. These functions are called getters and setters. To the outside world an accessor property looks like an ordinary property (user.age), yet behind the scenes your own code decides what reading or assigning it actually does.

This guide covers the get/set syntax, how accessor properties differ from data properties, the most common use cases (validation and computed values), how getters and setters work inside classes, and the gotchas worth knowing about.

Introduction to Property Getters and Setters

A getter is a function that runs when you read a property; its return value becomes the value of the access. A setter is a function that runs when you assign to a property; it receives the assigned value as its single argument. Because they are functions, they can run validation, compute a result on the fly, log access, or update other properties — all while the calling code uses plain property syntax.

Syntax

Inside an object literal, define a getter with the get keyword followed by a method, and a setter with the set keyword followed by a method that takes one parameter:

let obj = {
  get propName() {
    // getter, the code executed when obj.propName is read
  },
  set propName(value) {
    // setter, the code executed when obj.propName is written
  }
};

You may define both, or just one. A property with only a getter is read-only; assigning to it silently does nothing in non-strict mode and throws a TypeError in strict mode. A property with only a setter is write-only — reading it returns undefined.

Accessor properties vs. data properties

It is worth being precise about what kind of property a getter/setter creates. A regular property like width: 5 is a data property with a value. A getter/setter pair instead creates an accessor property that has no value of its own — only get and set functions. The two are mutually exclusive: a single property descriptor cannot have both a value and a get/set.

That is why the validation examples below keep the real number in a separate backing field (_age): the public age accessor needs somewhere to store the data, because it has no value slot of its own. To inspect this directly, see Property flags and descriptors.

Why Use Getters and Setters?

Getters and setters offer several benefits, including:

  • Encapsulation: They hide the internal representation behind a stable public interface. You can later change how a value is stored without breaking the code that reads it.
  • Validation: You can reject or normalize values in the setter before they are stored.
  • Computed Properties: A getter can derive its result from other properties, so the value is always up to date and never stored stale.
  • Backward compatibility: If a property that used to be a plain field needs logic added later, you can replace it with an accessor of the same name — calling code does not change.

Practical Examples

Let's dive into some practical examples to illustrate how getters and setters can be used in real-world scenarios.

Example 1: User Object with Age Validation

Consider a user object where we want to ensure that the age property is always within a reasonable range. The setter validates the input; the getter just returns the backing field.

javascript— editable

Example 2: Creating Computed Properties

Getters allow us to create properties that are computed on the fly based on other data. Every time area is read it is recalculated, so it stays in sync if width or height change.

javascript— editable

Example 3: Defining accessors with Object.defineProperty

The get/set literal syntax is the most common way to declare accessors, but you can also add them to an existing object — including after it was created — with Object.defineProperty. This is handy when the property name is dynamic or when you want to control flags like enumerable.

javascript— editable

Best Practices

When using getters and setters, consider the following best practices to ensure your code is clean, maintainable, and efficient:

  • Avoid Side Effects in Getters: Getters should be fast and free of side effects, as they are often called implicitly by the engine or during property enumeration.
  • Validation: Always validate data in setters to prevent invalid or harmful data from being stored.
  • Naming Conventions: Use a leading underscore (_) for the backing property names to indicate they are private.
  • JSON Serialization: Note that JSON.stringify() ignores getters by default. Use a replacer function or explicit serialization if you need to include computed values.

Advanced Use Cases

Dynamic Property Names

JavaScript ES6 introduced computed property names, which can be combined with getters and setters to dynamically define accessor keys based on variables or expressions.

javascript— editable

Integrating with Classes

Getters and setters are also highly useful in class-based programming, offering a way to encapsulate and control access to class properties. The syntax is identical — just write get/set methods in the class body — and they are placed on the prototype, so every instance shares them.

javascript— editable

Common Pitfalls

A few mistakes catch developers off guard:

  • Infinite recursion from a wrong backing field. If a setter for name assigns to this.name instead of a separate field like this._name, the assignment triggers the setter again, forever. Always store the value under a different key.
  • A getter without a setter is read-only. Assigning to it does nothing (or throws in strict mode), which can look like a silent bug.
  • JSON.stringify() calls getters but ignores setters. A computed getter is serialized (its return value is included), but there is no way to restore it through a setter on JSON.parse() — you only get back plain data.
  • this follows the call site. Inside a getter or setter, this is the object the property was accessed on. If you copy the accessor onto another object, this changes accordingly — see Object methods and "this".

The example below shows the recursion trap and its fix:

javascript— editable

Conclusion

Mastering property getters and setters is a crucial step towards becoming a proficient JavaScript developer. These features not only enhance the functionality and safety of your code but also pave the way for more readable and maintainable codebases. By following the best practices and examples provided in this guide, developers can effectively utilize getters and setters to their advantage, leading to more robust and efficient JavaScript applications.

Practice

Practice
Which statements are true regarding JavaScript getters and setters?
Which statements are true regarding JavaScript getters and setters?
Was this page helpful?