Reputation: 110257
Let's say I have the following object where I want to initialize it with values (outside a class):
let person = {
firstName: undefined,
lastName: undefined,
get fullName() {
return `${this.firstName} ${this.lastName}`;
}
}
let p = Object.create(person);
p.firstName = 'Ralph';
p.lastName = 'Smedley';
console.log(p.fullName);
Why doesn't the above work when doing the following?
let person = {
firstName: undefined,
lastName: undefined,
get fullName() {
return `${this.firstName} ${this.lastName}`;
}
}
// use default Object so don't override inherited object
let ralph = Object.assign({}, person, {firstName: 'Ralph', lastName: 'Smedley'});
console.log(ralph.fullName);
What would be the proper way to do this second approach?
Upvotes: 1
Views: 24
Reputation: 370809
When you use Object.assign
, the getters are invoked at that time (and the result is put as a data property onto the new object). Your getter isn't running after ralph
is created - it's running before that.
let person = {
firstName: undefined,
lastName: undefined,
get fullName() {
console.log('getting fullName');
return `${this.firstName} ${this.lastName}`;
}
}
let ralph = Object.assign({}, person, {firstName: 'Ralph', lastName: 'Smedley'});
After that occurs, you're left with an object of:
{
firstName: "Ralph"
fullName: "undefined undefined"
lastName: "Smedley"
}
So logging ralph.fullName
will give you what exists in that property, which is "undefined undefined"
Using Object.create
, on the other hand, does not invoke getters that may exist on the object - all it does is set the internal prototype.
If you wanted to copy over the method too, you could do:
const person = {
firstName: undefined,
lastName: undefined,
get fullName() {
return `${this.firstName} ${this.lastName}`;
}
};
const objectAssignWithGettersSetters = (target, ...args) => {
for (const arg of args) {
Object.defineProperties(target, Object.getOwnPropertyDescriptors(arg));
}
return target;
}
const ralph = objectAssignWithGettersSetters({}, person, {firstName: 'Ralph', lastName: 'Smedley'});
console.log(ralph.fullName);
Upvotes: 3