1

On MDN doc I couldn't understand this part about Object.defineProperty descriptor :

Bear in mind that these attributes are not necessarily the descriptor's own properties. Inherited properties will be considered as well. In order to ensure these defaults are preserved, you might freeze the Object.prototype upfront, specify all options explicitly, or point to null with Object.create(null).

what happens if I didn't preserve descriptor attributes? Are there unexpected things that may happen? example, please?

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
Ayman Morsy
  • 1,279
  • 1
  • 10
  • 28

1 Answers1

0

That's a very peculiar recommendation IMO, only for use in extraordinarily defensive code. Taking an example:

you might freeze the Object.prototype upfront, specify all options explicitly, or point to null with Object.create(null).

If you don't do this, then if you happen to have code that mutates Object.prototype (which you really shouldn't, in any sane situation), and the mutated Object.prototype adds properties used by the descriptor, those properties will be used even though they're not directly on the object. Like this:

// FOR INFORMATIONAL USE ONLY
// NEVER USE THIS NEXT LINE IN REAL CODE
Object.prototype.writable = true;


// then later:
const obj = {};
Object.defineProperty(obj, 'prop', { value: 'value' });
/* In normal circumstances, the resulting descriptor would be:

{
  value: 'value',
  enumerable: false,
  writable: false,
  configurable: false,
}

But because `writable` was inherited from Object.prototype is true, the property is writable:
*/
obj.prop = 'value2';
console.log(obj.prop);

A possible remedy to this is to freeze Object.prototype ahead of time, so that such mutation is impossible:

'use strict'; // so error below is explicit
Object.freeze(Object.prototype);

// FOR INFORMATIONAL USE ONLY
// NEVER USE THIS NEXT LINE IN REAL CODE
Object.prototype.writable = true;

Or to make sure that the descriptor object created doesn't inherit from Object.prototype:

// FOR INFORMATIONAL USE ONLY
// NEVER USE THIS NEXT LINE IN REAL CODE
Object.prototype.writable = true;


// then later:
const obj = {};
const descriptor = Object.create(null);
descriptor.value = 'value';
Object.defineProperty(obj, 'prop', descriptor);

obj.prop = 'value2';
console.log(obj.prop);

Or write out all values of the descriptor explicitly, without relying on the defaults:

// FOR INFORMATIONAL USE ONLY
// NEVER USE THIS NEXT LINE IN REAL CODE
Object.prototype.writable = true;


// then later:
const obj = {};
Object.defineProperty(obj, 'prop', {
  value: 'value',
  enumerable: false,
  writable: false,
  configurable: false,
});
obj.prop = 'value2';
console.log(obj.prop);

But in any remotely sane code, none of this should be necessary, because Object.prototype should never be mutated to begin with.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320