How Object.assign Handles Getters and Setters
When working with Object.assign() in JavaScript,
accessor properties (getters and setters) are not copied as descriptor
functions; instead, they are evaluated during the copy process. Because
Object.assign() uses standard [[Get]] and
[[Set]] internal methods, it executes the getter on the
source object to retrieve a static value, and then assigns that
evaluated value to the target object. It does not transfer the
underlying getter or setter logic to the destination object.
The Getter Mechanism on Source Objects
When a source object contains a getter property,
Object.assign() reads the property value. This read
operation invokes the getter function immediately at the time of
assignment.
const source = {
get time() {
return new Date().toISOString();
}
};
const target = Object.assign({}, source);
console.log(target.time); // Outputs the timestamp generated during the assign call
// target.time is now a static string, not a getter functionIn the example above, target.time becomes a regular data
property holding the string returned by the getter, rather than
remaining a dynamic property.
The Setter Mechanism on Target Objects
When assigning a value to the target object,
Object.assign() triggers any existing setter defined on
that target.
const target = {
set data(value) {
this._data = value.toUpperCase();
}
};
const source = { data: 'hello' };
Object.assign(target, source);
console.log(target._data); // "HELLO"If the target object does not have an existing setter for that
property key, Object.assign() simply creates a standard,
writable, enumerable, and configurable data property.
Preserving Accessor Descriptors
To properly copy property descriptors—including getters, setters,
enumerability, and writability—without evaluating them, use
Object.getOwnPropertyDescriptors() in combination with
Object.defineProperties().
const source = {
get dynamicValue() {
return Math.random();
}
};
// Preserves the getter function on the new object
const target = Object.defineProperties(
{},
Object.getOwnPropertyDescriptors(source)
);
console.log(target.dynamicValue !== target.dynamicValue); // true (getter executes on each access)By using Object.defineProperties(), the property
definition is cloned directly, allowing the target object to retain the
original accessor behavior.