user1931754
user1931754

Reputation:

javascript:object

At last there i see a smell of closure in the following code.

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"//value is changed now

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

the value of object1.a ,abject2.a is changed permamently .Is this because i made a change in global variable or that is the affect of closure?since i have not invoked the Create() function again why is the value changed automatically? last question "when i made a change in global variable does that automatically affect all the object using tht variable?"in my view to make an effect of that variable i should call the Create() function again isn't it?

Upvotes: 1

Views: 87

Answers (3)

Arturo E
Arturo E

Reputation: 303

This happens because of how inheritance works in prototype-based languages, such as javascript. When you call create(masterObject), you are returning a new instance of a function object (that you call F) with its prototype set to masterObject. That means that the prototype field for object1, object2, and object3 point to the same object, masterObject.

The statement:

object3.a  = "overriden value"

creates a field called a in object3 and assigns it the string "overriden value", and thats what you get when you examine object3.a. But when you look at object1.a, the interpreter notices that the a field does not exist in object1 so it follows the prototype link to its parent and examines that for a field called a. In this case, the prototype link points to masterObject which has a field called a that holds the string "masterObject value" and thats what you see. If masterObject did not have a field called a, the interpreter would follow the prototype link again and again until it finds an a field or until it reaches an object with an empty prototype link and it will then return the value undefined.

So by changing masterObject.a, you change what you see when you examine object1.a and object2.a because object1 and object2 do not have a field called a, so they "inherit" it from their parent, masterObject.

This does not happen when you examine object3.a because you created a field called a in object3 that holds the string "overridden value".

If, at the end of your code, you add:

delete object3.a;

you would now see "new masterObject value" when you look at object3.a, because object3 no longer has a field called a, so it "inherits" it from its parent, masterObject.

Upvotes: 0

Blender
Blender

Reputation: 298046

When you access object3.a, JavaScript first looks at the object's properties. If the object doesn't have a property called a, the object's prototype is checked next.

Setting object3.a = "overridden value"; gives object3 a property called a. It doesn't affect your prototype's a property.

Since object1 and object2 don't have a property called a, but their prototype does, when you modify masterObject's a property, the value changes globally for all objects that have masterObject as their prototype.

Even though you gave object3 a property called a, but you can still access the prototype's a property, which remains the same:

object3.__proto__.a; // "new masterObject value"

Basically, by giving object3 a property called a, you're putting the object's new property "in front" of the prototype's property.

Upvotes: 3

gustaf r
gustaf r

Reputation: 1234

When you alter an object's 'a' property directly (as you do with var object3.a = "overridden value"; (which shouldn't have a var in front of it), you alter that instance's own 'a' property.

So, what really happens is:

object3.a = "overridden value"; here you create a new property on object3. It didn't have an 'a' property before. Its prototype did however, so object3.a was legal and would refer to the prototype's 'a' property.

masterObject.a = "new masterObject value" here you alter the prototype of all objects (created by create()). So if you access the property 'a' on objects, it will now be changed, except for those which have their own 'a' properties (such as object3).

Upvotes: 0

Related Questions