Reputation: 13
In the following example i have a simple Spy object. I wanted to create another object setting the prototype with the original object, so I've used Object.create().
Now I have a new object, which have just some properties from the original ('code' and 'breath' method). All the other properties (objects - 'name' and arrays - 'enemies') are in the _proto_ object, which i can use, because they are delegated to the original object. So far so good.
The tricky part is that if I change anything in the AnotherSpy included in the _proto_ object (the object name for example), those changes will be reflected in all the objects created from the original spy, including himself!
I also tried create a new object with using JSON.parse(), but in this way I have a new object which only have access to the 2 things that were previously in the _proto_ object - the array of enemies and the name object, without being able to use any methods of the original object (the 'breath' method).
let Spy = {
code: '007',
enemies: ['Dr.No'],
fullName: {
firstName: 'James',
lastName: 'Bond'
},
breath: function() {
console.log('im breathing..')
}
}
// original Spy breathing
Spy.breath(); // ok, he breaths
// create a new object with Object.create()
let OtherSpy = Object.create(Spy);
console.log(OtherSpy) // have direct access to properties 'code' and function 'breath' and all the others throught the __proto__ object
// Make OtherSpy breath
OtherSpy.breath(); // ok, he is breathing
// so far so good. Lets change the property and function on the OtherSpy
OtherSpy.code = '008';
OtherSpy.breath = () => {
console.log('im a new breathing')
};
OtherSpy.breath(); // ok, he's breathing differently
console.log(Spy.code); // 007 ok, original spy has the same code
Spy.breath() // ok, he stills breath in the same way.
// change the object 'name' of the OtherSpy
OtherSpy.fullName.firstName = 'Enemy';
// That change will reflect also on the original Spy...
console.log(Spy.fullName.firstName); // Enemy !!!!
// Trying in another way:
let NewSpy = JSON.parse(JSON.stringify(Spy));
console.log('NewSpy')
console.log(NewSpy) // now i dont have access to methods in the original object
NewSpy.breath() // Uncaught TypeError: NewSpy.breath is not a function
It seems that all properties included in the _proto_ object are shared in all objects that use that prototype chain.
Aside from this tricky parts that would greatly appreciate an explanation, I would like to know the proper way to create an object in JavaScript (without using ES6 classes) in order to get the advantage of the prototype delegation
and to be able to modify the properties and functions of the derived object without messing up with the original object nor any other derived objects.
Thanks in advance!
Upvotes: 1
Views: 130
Reputation: 138477
Nested properties are somewhat unuseful, so you may flatten it through using getters/setters:
const Spy = {
firstName: "Agent",
lastName: "Unnamed",
breath(){
console.log(`${this.fullName} is breathing`);
},
get fullName(){
return this.firstName + " " + this.lastName;
},
set fullName(name){
const [first, last] = name.split(" ");
this.firstName = first;
this.lastName = last;
}
};
const james = Object.create(Spy);
james.fullName = "James Bond";
james.breath();
console.log(james.fullName, james.firstName, james.lastName);
Upvotes: 1
Reputation: 138477
Another way would be to construct the name
object inside of an constructor:
function Spy(name, code, enemies){
this.name = (([first, last]) => ({first, last}))(name.split(" "));
this.name.toString = () => name;
this.code = code;
this.enemies = enemies;
}
Spy.prototype = {
breath(){
console.log(`${this.name} is breathing`);
}
}
Usable as:
const james = new Spy("James Bond", "007", ["Dr. No"]);
james.breath();
console.log(james.name, "" + james.name);
Upvotes: 1