Property Shadowing & Enumeration
What is Prototype?
JavaScript objects inherits features (methods
and properties
) from one another through a mechanism named Prototype
.
What is Prototype Chain?
An object's prototype may further have a prototype object, from which it inherits methods and properties (so on and so forth). This is referred to as prototype chain
. When trying to access a property of an object, JavaScript will first search for the property on the object, followed by the object’s prototype, followed by the object’s prototype prototype and so on till it find the property or till the end of prototype chain i.e. null
.
What is Property Shadowing?
When you are creating a property on an object which has the same property name as on its prototype chain, it will not be evaluated and enumerated i.e. properties with same name are shadowed and therefore will not be enumerated. This implies that property
defined on object
is evaluated first before looking into its prototype property.
output = [];
for (var x in Object.create(
{a:10, b:20, c:30}, {a:{value:40},
b:{value:50, enumerable:true}}))
output.push(x) ;
console.log(output.toString());
Output:
b,c
Explanation:
- All properties in the prototype chain should be enumerated, but the same property name is never enumerated twice.
- Properties in the prototype chain with the same name are shadowed and therefore are not enumerated.
- Here,
a
isenumerable:false
in it'sprototype
, hence is not enumerated.
Syntax
Object.create(proto)
Object.create(proto, propertiesObject)
Let's store the Object in a variable x1
var x1 = Object.create(
{a:10, b:20, c:30}, {a:{value:40},
b:{value:50, enumerable:true}})
Now, lets print x1
. It contains the following - prototype
and propertiesObject
x1
{b: 50, a: 40}
b: 50
a: 40
__proto__:
a: 10
b: 20
c: 30
__proto__: Object
The Object.keys()
method returns an array of a given object's own enumerable property names. So as we see here, a
is not enumerable.
Object.keys(x1)
["b"]
But, if we try to evaluate x1.b
it is not undefined
x1.b
50
The Object.getOwnPropertyNames()
method returns an array of all properties (including non-enumerable properties except for those which use Symbol) found directly in a given object.
Let's check the output
Object.getOwnPropertyNames(x1)
(2)["a", "b"]
The Object.getOwnPropertyDescriptors()
method returns all own property descriptors of a given object.
Object.getOwnPropertyDescriptors(x1)
{a: {…}, b: {…}}
a: {value: 40, writable: false, enumerable: false, configurable: false}
b: {value: 50, writable: false, enumerable: true, configurable: false}
__proto__: Object
If we look in the above output, a
is enumerable: false
. But b
is true
as we have manually set it to true
.
Object.getOwnPropertyDescriptors(x1.__proto__)
{a: {…}, b: {…}, c: {…}}
a: {value: 10, writable: true, enumerable: true, configurable: true}
b: {value: 20, writable: true, enumerable: true, configurable: true}
c: {value: 30, writable: true, enumerable: true, configurable: true}
__proto__: Object
If we look in the above output c
is enumerable: true. Hence c
is printed in the output.
Hence, finally in the output b
and c
are enumerated and we get b,c
as the output. Hope this explains the concept in detail.
Happy Learning!
Like | Comment | Save | Share |