I have created below two employee classes, one using a constructor function and the other with JSON notation. In the constructor function, the print function is created by prototype so only one copy will be kept and objects (emp1 and emp2) share this print function.
Question: In the JSON notation (EmployeeNew), will the print function be held in memory as one copy only? Or will each object keep its own copy? What is the fundamental difference between these two approaches? Which is best for which scenario?
var Employee = function (name) {
this.name = name;
};
Employee.prototype.print = function () {
console.log(this.name);
}
var emp1 = new Employee("jack"),
emp2 = new Employee("mark");
emp1.print();
emp2.print();
var EmployeeNew = {
init: function (name) { this.name = name; },
print: function () {
console.log(this.name);
}
};
var empNew1 = Object.create(EmployeeNew),
empNew2 = Object.create(EmployeeNew)
empNew1.init("jack")
empNew1.print();
empNew2.init("jack");
empNew2.print();
Your two code examples are generally equivalent (except for some minor details not relevant to the question).
This...
Object.create(EmployeeNew)
...creates a new object with the EmployeeNew object as its prototype. So the print and init functions are shared.
console.log(empNew1.init === empNew2.init); // true
console.log(empNew1.print === empNew2.print); // true
To further illustrate, here's an example that takes the following steps...
EmployeeNew object to be used by Object.createObject.createEmployeeNewEmployeeNewStep 1: Create an EmployeeNew object
var EmployeeNew = {
init: function (name) { this.name = name; },
print: function () {
console.log(this.name);
}
};
Step 2: Create 2 unique objects using Object.create
var empNew1 = Object.create(EmployeeNew),
empNew2 = Object.create(EmployeeNew)
Step 3: Verify that the new objects can use the functions provided by EmployeeNew
empNew1.init("jack");
empNew1.print();
empNew2.init("jack");
empNew2.print();
Step 4: Add a new function to EmployeeNew
EmployeeNew.foo = function() {
console.log( 'Foo was invoked' );
};
Step 5: See if the objects from step 2 can use that new function
empNew1.foo(); // logs 'Foo was invoked'
empNew2.foo(); // logs 'Foo was invoked'
So you can see that empNew1 and empNew2 are able to observe changes to EmployeeNew. This is because when we passed EmployeeNew as the first argument to Object.create, we created a new object with EmployeeNew set as the prototype of that object.
In simpler terms, when we look up a property, for example on empNew1, if empNew1 doesn't have that property, it automatically looks to its prototype to see if the property exists on that object. If so, it uses it.
With respect to your comment...
"...suppose, if create this.name as property ( name : "") is the name property also will be treated as prototype..."
Yes, if we do this...
EmployeeNew.name = "unknown"
...then that property will be shared among all instances that have EmployeeNew as their prototype object.
Because the .name property on the prototype is an immutable primitive value (a string), if we try to write to that property, what happens is that the .name property is automatically added directly to the instance.
Continuing with the example above...
EmployeeNew.name = "unknown";
Now the previously created instances will reference that property...
empNew1.name; // "unknown"
empNew2.name; // "unknown"
...but now lets update the property on one instance...
empNew1.name = "bubba";
empNew1.name; // "bubba"
empNew2.name; // "unknown"
This is because empNew1 now has its own .name property that references "bubba". This shadows the .name property on the prototype of empNew1, so the search for that property never extends into the prototype object.
Since empNew2 wasn't assigned a .name, it still looks to its prototype for that property.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With