class UserProfile {
constructor(name) {
this.name = name;
this.friends = [];
}
addFriend(friend) {
this.friends.push(friend);
}
render() {
return {
name: this.name,
friendCount: this.friends.length,
listFriends() {
return this.friends.map(friend => friend.name).join(', ');
}
};
}
}
const user = new UserProfile('Tyler');
user.addFriend({ name: 'Lynn' });
user.addFriend({ name: 'Ben' });
const profileData = user.render();
console.log(`${profileData.name} has ${profileData.friendCount} friends.`);
console.log(`Friends: ${profileData.listFriends()}`);
The bug is in the listFriends method inside the render method.
render() {
return {
name: this.name,
friendCount: this.friends.length,
listFriends() {
return this.friends.map(friend => friend.name).join(', ');
}
};
}
When listFriends is called, this no longer refers to the UserProfile instance, but instead to the object returned by render. This object doesn’t have a friends property, so this.friends is undefined. To fix this, you could use an arrow function to preserve the correct this context:
render() {
return {
name: this.name,
friendCount: this.friends.length,
listFriends: () => {
return this.friends.map(friend => friend.name).join(', ');
}
};
}
or if you’re a sicko, you could use .bind.
render() {
return {
name: this.name,
friendCount: this.friends.length,
listFriends: function() {
return this.friends.map(friend => friend.name).join(', ');
}.bind(this)
};
}