The object literal used in the inherited property modifies all instances of the class

I have the following code (ObjA), and it works as I would expect, an instance of "a1" has the same properties as "a2", but with different values.

function ObjA() { this.objLiteral = {}; this.propA = 0; } var a1 = new ObjA(); a1.objLiteral['hello'] = 3; a1.propA = 1.5; var a2 = new ObjA(); a2.objLiteral['goodbye'] = 4; a2.propA = 2; 

debug information for a1 and a2:
http://www.flickr.com/photos/ 76617756@N02 / 6879283032 /

Then I have the next ObjB that inherits from ObjA. The instances "b1" and "b2" have the same properties and different values ​​for the propA and propB properties, but for some reason objLiteral is the same in both cases, as if it were referencing the same object.

 ObjB.prototype = new ObjA(); ObjB.prototype.constructor=ObjB; function ObjB() { this.propB = 2; } var b1 = new ObjB(); b1.objLiteral['hello2'] = 6; b1.propA = 4; b1.propB = 5; var b2 = new ObjB(); b2.objLiteral['goodbye2'] = 8; b2.propA = 6; b2.propB = 7; 

debugging information for b1 and b2:
http://www.flickr.com/photos/ 76617756@N02 / 6879283088 /

Can someone help me understand what is happening? What should I do to find out what I expect? Your help is greatly appreciated.

+4
source share
1 answer

Well, both objects b1 and b2 have a prototype of the same , namely an instance of ObjA :

 ObjB.prototype = new ObjA(); 

therefore, they inherit and have access to their properties. b1.objLiteral and b2.objLiteral refer to the same object:

enter image description here

and

 > b1.objLiteral === b2.objLiteral true 

To fix this, you need to create a new object for each instance. This is usually done by calling the constructor "parent" inside the constructor "child":

 function ObjB() { ObjA.call(this); this.propB = 2; } 

ObjA.call(this) will call ObjA and inside this function this will refer to the argument passed to call [MDN] , in this case a new instance of ObjB :

enter image description here

As you can see, objLiteral now a property of each instance:

 > b1.objLiteral === b2.objLiteral false 

To avoid this confusion in the first place, you should avoid installing an instance of the parent constructor as a prototype of the child constructor. What if the parent constructor expects specific instance arguments? What would you switch to ObjA in this case?

Better install prototype child constructor prototype parent constructor (with one level of indirection) and call the parent constructor as above:

 function inherit(Child, Parent) { var Tmp = function() {}; Tmp.prototype = Parent.prototype; Child.prototype = new Tmp(); Child.prototype.constructor = Child; } inherit(ObjB, ObjA); 

Tmp to prevent the Parent.prototype extension if you continue Child.prototype .


Regarding propA :

It "works" because you assign it a new meaning.

Here again the objects, after assigning the properties x.objLiteral and x.propA . You can see that the objects do not have their own objLiteral property, but their own propA :

enter image description here

If instead you assign a new value to objLiteral , for example. through

 b1.objLiteral = {hello: 42}; 

b1 will now have its own objLiteral property, which is the shadow of the inherited:

enter image description here

+3
source

Source: https://habr.com/ru/post/1404030/


All Articles