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
const obj = {};
obj.prop = 3;
assert.deepEqual(
Object.getOwnPropertyDescriptors(obj),
{
prop: {
value: 3,
writable: true,
enumerable: true,
configurable: true,
}
});
9.8.2 Own properties created via object literals
const obj = { prop: 'yes' };
assert.deepEqual(
Object.getOwnPropertyDescriptors(obj),
{
prop: {
value: 'yes',
writable: true,
enumerable: true,
configurable: true
}
});
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:
> Object.getOwnPropertyDescriptor([], 'length')
{ value: 0, writable: true, enumerable: false, configurable: false }
> Object.getOwnPropertyDescriptor('abc', 'length')
{ 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
assert.deepEqual(
Object.getOwnPropertyDescriptor(Array.prototype, 'map'),
{
value: Array.prototype.map,
writable: true,
enumerable: false,
configurable: true
});
9.8.5 Prototype properties and instance properties of user-defined classes
class DataContainer {
accessCount = 0;
constructor(data) {
this.data = data;
}
getData() {
this.accessCount++;
return this.data;
}
}
assert.deepEqual(
Object.getOwnPropertyDescriptors(DataContainer.prototype),
{
constructor: {
value: DataContainer,
writable: true,
enumerable: false,
configurable: true,
},
getData: {
value: DataContainer.prototype.getData,
writable: true,
enumerable: false,
configurable: true,
}
});
Note that all own properties of instances of DataContainer
are writable, enumerable, and configurable:
const dc = new DataContainer('abc')
assert.deepEqual(
Object.getOwnPropertyDescriptors(dc),
{
accessCount: {
value: 0,
writable: true,
enumerable: true,
configurable: true,
},
data: {
value: 'abc',
writable: true,
enumerable: true,
configurable: true,
}
});