What's the Difference Between Data Property and Accessor Property in JavaScript?

In JavaScript, an object property can be of one of the following types:

  1. Data property, or;
  2. Accessor property.

These properties differ in terms of how they can be configured using their respective property descriptors. The following property descriptors are common to both:

  • enumerable — if true, the property will show up during enumeration of the object properties;
  • configurable — if false, it prevents deletion of the property as well as any changes to the object property's descriptors.

In addition to those, a data property has the following descriptors:

  • value — any value that's associated with the property;
  • writable — if true, the property value can be reassigned.

In case of data properties, if configurable is set to false, then the value descriptor may still be reassigned if the writable descriptor is set to true.

In contrast, an accessor property has the following descriptors in addition to the common ones between the two:

  • get — a getter function for the property;
  • set — a setter function for the property.

Please note that if an object property descriptor does not (at the very least) have one of; value, writable, get or set descriptors then it is treated as a data property by default.

An object property descriptor can either be a data property descriptor or an accessor property descriptor; it cannot be both. If a descriptor has both; [value and/or writable] and [get and/or set] keys, then an exception is thrown.

In summary, it can be concluded that:

For example, a data property can be defined at the time of object creation like so:

const obj = { foo: 'bar' };
const descriptors = Object.getOwnPropertyDescriptor(obj, 'foo');

console.log(descriptors); // { value: 'bar', writable: true, enumerable: true, configurable: true }

Alternatively, you may use the Object.defineProperty() to create a data property in the following way:

const obj = {};

Object.defineProperty(obj, 'foo', { value: 'bar' });

const descriptors = Object.getOwnPropertyDescriptor(obj, 'foo');

console.log(descriptors); // { value: 'bar', writable: false, enumerable: false, configurable: false }

Similarly, an accessor property can be defined at the time of object creation like so:

const obj = {
  get foo() { return this._foo; },
  set foo(value) { this._foo = value; },
};
const descriptors = Object.getOwnPropertyDescriptor(obj, 'foo');

console.log(descriptors); // { enumerable: true, configurable: true, get: ƒ, set: ƒ }

Alternatively, you may use the Object.defineProperty() to create an accessor property in the following way:

const obj = {};

Object.defineProperty(obj, 'foo', {
  get() { return this._foo; },
  set(value) { this._foo = value; },
});

const descriptors = Object.getOwnPropertyDescriptor(obj, 'foo');

console.log(descriptors); // { enumerable: false, configurable: false, get: ƒ, set: ƒ }

Please be aware that the default values for property descriptors are different when you use the Object.defineProperty() (or Object.create) method as compared to directly defining them at object creation.


This post was published by Daniyal Hamid. Daniyal currently works as the Head of Engineering in Germany and has 20+ years of experience in software engineering, design and marketing. Please show your love and support by sharing this post.