9.8 What property attributes do built-in constructs use?

The general rule (with few exceptions) for property attributes is:

  • Properties of objects at the beginning of a prototype chain are usually writable, enumerable, and configurable.

  • As described in the chapter on enumerability, most inherited properties are non-enumerable, to hide them from legacy constructs such as for-in loops. Inherited properties are usually writable and configurable.

9.8.1 Own properties created via assignment

  1. const obj = {};
  2. obj.prop = 3;
  3. assert.deepEqual(
  4. Object.getOwnPropertyDescriptors(obj),
  5. {
  6. prop: {
  7. value: 3,
  8. writable: true,
  9. enumerable: true,
  10. configurable: true,
  11. }
  12. });

9.8.2 Own properties created via object literals

  1. const obj = { prop: 'yes' };
  2. assert.deepEqual(
  3. Object.getOwnPropertyDescriptors(obj),
  4. {
  5. prop: {
  6. value: 'yes',
  7. writable: true,
  8. enumerable: true,
  9. configurable: true
  10. }
  11. });

9.8.3 The own property .length of Arrays

The own property .length of Arrays is non-enumerable, so that it isn’t copied by Object.assign(), spreading, and similar operations. It is also non-configurable:

  1. > Object.getOwnPropertyDescriptor([], 'length')
  2. { value: 0, writable: true, enumerable: false, configurable: false }
  3. > Object.getOwnPropertyDescriptor('abc', 'length')
  4. { value: 3, writable: false, enumerable: false, configurable: false }

.length is a special data property, in that it is influenced by (and influences) other own properties (specifically, index properties).

9.8.4 Prototype properties of built-in classes

  1. assert.deepEqual(
  2. Object.getOwnPropertyDescriptor(Array.prototype, 'map'),
  3. {
  4. value: Array.prototype.map,
  5. writable: true,
  6. enumerable: false,
  7. configurable: true
  8. });

9.8.5 Prototype properties and instance properties of user-defined classes

  1. class DataContainer {
  2. accessCount = 0;
  3. constructor(data) {
  4. this.data = data;
  5. }
  6. getData() {
  7. this.accessCount++;
  8. return this.data;
  9. }
  10. }
  11. assert.deepEqual(
  12. Object.getOwnPropertyDescriptors(DataContainer.prototype),
  13. {
  14. constructor: {
  15. value: DataContainer,
  16. writable: true,
  17. enumerable: false,
  18. configurable: true,
  19. },
  20. getData: {
  21. value: DataContainer.prototype.getData,
  22. writable: true,
  23. enumerable: false,
  24. configurable: true,
  25. }
  26. });

Note that all own properties of instances of DataContainer are writable, enumerable, and configurable:

  1. const dc = new DataContainer('abc')
  2. assert.deepEqual(
  3. Object.getOwnPropertyDescriptors(dc),
  4. {
  5. accessCount: {
  6. value: 0,
  7. writable: true,
  8. enumerable: true,
  9. configurable: true,
  10. },
  11. data: {
  12. value: 'abc',
  13. writable: true,
  14. enumerable: true,
  15. configurable: true,
  16. }
  17. });