If I use prototypical inheritance in Javascript, the methods are available in subclasses but the members from parent are shared. Why is this?
For eg, I am extending 2 data structure classes from my store.
function Store() {
this._store = [];
this._index = -1;
}
Store.prototype.addData = function (val) {
this._index++;
this._store[this._index] = val;
};
Store.prototype.toString = function() {
return "Store: [" + this._store + "]";
};
// inherits from Store
function DS1() {
}
DS1.prototype = new Store();
DS1.prototype.constructor = DS1;
Now if I use 2 instances of DS1, they are using the same store data. Why is that?
var ds1 = new DS1();
ds1.addData(2);
console.log(ds1.toString()); // Prints 2
var ds2 = new DS1();
ds2.addData(3);
console.log(ds2.toString()); // Prints 3
console.log(ds1.toString()); // Prints 3 and NOT 2.
This is one reason why use of new
is discouraged for use with prototype
. The problem is that a new unique _data
array is created only when your Store
constructor runs. Your Store
constructor only runs one time , ever, in DS1.prototype = new Store();
This means that all new DS1()
instances share the same _data
array.
Here's an relevant example adapted from a different answer of mine . Suppose each Store
has a pseudo-unique, random id
property:
var Store = function() {
// each Store instance has a random id
this.id = Math.random();
}
Store.prototype.addData = function() { /* ... */ }
Then, you want DS1
to inherit from Store
:
var DS1 = function() {
this.something = 5;
}
DS1.prototype = new Store(); // this is bad
var ds1 = new DS1();
console.log(ds1.id);
var ds2 = new DS1();
console.log(ds2.id); // same as ds1!
Bad news -- DS1
instances all share the same id
now! DS1.prototype.id
is set once, ever, on the line DS1.prototype = new Store();
, and that's where all DS1
instances get their id
from.
Instead, you want to run the Store
constructor code each time you run the DS1
constructor code, instead of just once when your set up the DS1
prototype:
var DS1 = function() {
Store.call(this); // set parent constructor properties on `this` new DS1 obj
//...
}
// DS1 prototype inherits from Store prototype, not Store instance
DS1.prototype = Object.create(Store.prototype);
This is because in Javascript object are not copied by value but only by reference
.Now, the prototypes of children (here ds1, ds2) and parents point to same object, when a child modifies the prototype, the parents get the changes and so do the siblings. Inheritance in javascript
can be achieve by creating empty function F() setting its prototype to prototype of parent constructor as below.
function extend(Child, Parent) {
var F = function () {};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
Child.uber = Parent.prototype;
}
This way you can inherit by simply using extend(ds1, Store)
; Inheritance and prototype chain
Add Store.call(this)
to your DS1
"class". After that you can start assigning values for your DS1
specific properties inside the constructor.
As it was said in comments, all childs uses the same object as a prototype. That is how prototypical inheritance works.
The prototype object in such kind of inheritance stands as a spare storage of methods and variables for child objects.
When you call/get a var from d1
or d2
it looks if they have addData
. They haven't. Then js looks into __prototype. Hey, new Store
is there! Does it have a addData
? Yes! Calling it...
It's important, that new Store
is called once, so a created object stands for all childs of your parent.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.