I am confused by the way property getters interact with constructor closure.
Below is a minimal example:
function Ctor() {
let closureX = 0
Object.assign(this, {
get publicX() { return closureX }
})
closureX++
console.log(closureX)
}
let o = new Ctor()
console.log(o.publicX)
Why is o.publicX
not changing when closureX
does ?
>Solution :
It is simply because that’s what Object.assign
does – it does not assign getters
or setters
, it assigns the values associated with the keys to the other object. MDN Docs already clarifies that getters will be invoked on the source and setters will be invoked on the target:
The
Object.assign()
method only copies enumerable and own properties from a source object to a target object. It uses[[Get]]
on the source and[[Set]]
on the target, so it will invoke getters and setters. Therefore it assigns properties, versus copying or defining new properties. This may make it unsuitable for merging new properties into a prototype if the merge sources contain getters.
That last sentence is exactly what you are trying to do and it will not work.
You can verify this be checking its property descriptor and seeing that the new object did not inherit the getter
from the source object, only the value
that getter returns:
const object = Object.assign({}, {
get publicX(){ return 3; }
});
console.log( object );
const definition = Object.getOwnPropertyDescriptor( object, 'publicX' )
console.log( definition ); // No getter defined, just a value
If you do want to accomplish this, the solution would probably be the old-fashioned Object.defineProperty
to assign the getter:
function Ctor(){
let closureX = 0;
Object.defineProperty(this, 'publicX', {
get(){ return closureX; }
});
closureX++;
}
const ctor = new Ctor();
console.log( ctor.publicX ); // It now returns the internal variable!