Five Techniques for Adding Getters and Setters to JavaScript Objects

Method 1: Using Object Initializer Syntax

Define getters and setters during object creation using literal syntax:

(function () {
  const obj = {
    value: 7,
    get computedValue() {
      return this.value + 1;
    },
    set multiplier(newValue) {
      this.value = newValue / 2;
    }
  };
  
  console.log(obj.value);         // 7
  console.log(obj.computedValue); // 8
  obj.multiplier = 50;
  console.log(obj.value);         // 25
})();

In Chrome debugging, you'll notice the object now includes special getter and setter properties. The output shows how these methods allow indirect modification of internal properteis.

A common question arises: Can we name the getter/setter methods the same as the internal property? Attempting this creates infinite recursion:

(function () {
  const obj = {
    value: 7,
    get value() {           // This causes infinite recursion
      return this.value + 1;
    },
    set value(newValue) {   // This also causes infinite recursion
      this.value = newValue / 2;
    }
  };
  // This will cause maximum call stack error
  // console.log(obj.value);
})();

When accessing obj.value, it calls the getter method, which again accesses this.value, creating an endless loop that results in a stack overflow error.

ES6 Syntax (currently supported primarily in Firefox):

(function () {
  const propName1 = "getterKey";
  const propName2 = "setterKey";
  
  const obj = {
    value: 7,
    get [propName1]() {
      return this.value + 1;
    },
    set [propName2](newValue) {
      this.value = newValue / 2;
    }
  };
  
  console.log(obj.value);                    // 7
  console.log(obj[propName1]);              // 8
  obj[propName2] = 50;
  console.log(obj.value);                   // 25
})();

Method 2: Using Object.create()

The Object.create() method creates objects with specified prototypes and properties:

(function () {
  const obj = Object.create(
    Object.prototype, // prototype
    {
      internalProperty: {
        get: function() {
          return this._data || 42;
        },
        set: function(value) {
          this._data = value * 2;
        },
        enumerable: true,
        configurable: true
      }
    }
  );
  
  console.log(obj.internalProperty); // 42 (default)
  obj.internalProperty = 10;
  console.log(obj.internalProperty); // 20
})();

The second parameter accepts a property descriptor object where each property's configuration includes data descriptors or accessor descriptors. Accessor descriptors enable adding getter and setter methods to newly created objects.

Method 3: Using Object.defineProperty()

Direct define individual properties with specific descriptors:

(function () {
  const obj = {};
  
  let internalValue = 10;
  
  Object.defineProperty(obj, 'calculated', {
    get: function() {
      return internalValue * 3;
    },
    set: function(newValue) {
      internalValue = newValue;
    },
    enumerable: true,
    configurable: true
  });
  
  console.log(obj.calculated); // 30
  obj.calculated = 5;
  console.log(obj.calculated); // 15
})();

Method 4: Using Object.defineProperties()

Define multiple properties at once:

(function () {
  const obj = {};
  let counter = 0;
  
  Object.defineProperties(obj, {
    increment: {
      get: function() {
        return ++counter;
      },
      enumerable: true
    },
    currentCount: {
      get: function() {
        return counter;
      },
      set: function(value) {
        counter = value;
      },
      enumerable: true
    }
  });
  
  console.log(obj.increment);     // 1
  console.log(obj.currentCount);  // 1
  obj.currentCount = 5;
  console.log(obj.currentCount);  // 5
})();

Method 5: Using Class Syntax (ES6+)

Modern approach using class declarations:

(function () {
  class DataContainer {
    constructor(initialValue = 0) {
      this._storage = initialValue;
    }
    
    get processedData() {
      return this._storage * 2 + 1;
    }
    
    set processedData(value) {
      this._storage = (value - 1) / 2;
    }
  }
  
  const container = new DataContainer(5);
  console.log(container.processedData); // 11
  container.processedData = 15;
  console.log(container._storage);      // 7
})();

Each method offers different advantages depending on when and how you need to add getters and setters to you're JavaScript objects.

Tags: javascript Getters Setters Object Properties ES6

Posted on Mon, 14 Sep 2026 16:17:09 +0000 by markbm