Prototype chain confusion

Hi all,

Please take a look at the below code in JS.
My Question:
In the create function, the parent is copied by reference. A new object is created of “F” and returned. However, if I change the value of the “masterObject”, it is reflected in “Object1” and “Object2” but not “object3”.

I don’t understand why this is. Even when I think of prototype, I still don’t get it. Please help me understand.


function create(parent) {
  var F = function() {};
  F.prototype = parent;
  return new F();
}

var masterObject = {a: "masterObject value"}

var object1 = create(masterObject);
var object2 = create(masterObject);
var object3 = create(masterObject);
var object3.a = "overridden value";

object1.a; // "masterObject value"
object2.a; // "masterObject value"
object3.a; // "overridden value"

masterObject.a = "new masterObject value"

object1.a; // "new masterObject value"
object2.a; // "new masterObject value"
object3.a; // "overridden value"

You are getting object3.a and object3.prototype.a mixed up.

The create copies the prototype. The prototype properties are only accessible without specifically referencing the prototype until such time as you attach a property with the same name directly to the object. Once you have defined object3.a you can no longer use that name to reference object3.prototype.a until such time as you delete object3.a

If you were to delete object3.a and then try to reference it you will once again be accessing the prototype and will see the value that you updated in masterObject.

Thanks that really helped.

Hey, I can’t help but ask the following question. Why can’t I do this
object3.prototype.a = “b” … I want to use the object3 to change the value in the prototype. So, I would be changing the value of the “masterObject” via the object3.

I’m just curious why I can’t change the prototype value. It’s only letting me override the property.

Thanks again for the help

You can use proto to go up the prototype chain, which allows you to get to the masterObject to make the change.

Felgall may have a better understanding than me though on the details of why the standard prototype isn’t able to be used in your situation.

The parent object is supposed to be a template from which you create objects using the create function. While you can modify the create function to allow changes to one object to be applied to all the other objects as well, you can’t do it by changing that template object.

The following allows you to change the property for all the child objects in one go by creating another property that points back at the template (provided of course that none of them have created a property with the same name as the prototype one):

function create(parent) {
  var F = function() {};
  F.prototype = parent;
  n = new F();
  n.uber = parent;
  return n;
}
 
var masterObject = {a: "masterObject value"}
var object1 = create(masterObject);
var object2 = create(masterObject);
var object3 = create(masterObject);
object3.uber.a = "overridden value";

alert(object1.a); // "overridden value"
alert(object2.a); // "overridden value"
alert(object3.a); // "overridden value"

I am not sure that I fully understand this myself but when you use either of those versions of create() the prototype for the object you assign it to us undefined. This variant creates your own replacement for it called uber (which is the German word for super without the umlaut - which was suggested by Douglas Crockford as an appropriate name to use for it since many other languages eg. Java refer to it by the name super which is unfortunately not available for this use in JavaScript).