it could be old question but i still not able to understand the theory behind it.
we have
function Test(name) {
this.name = name;
}
Test.prototype.myArray = []; // I know if i move this to constructor it can resolve my problem
Test.prototype.what = function() {
document.writeln("<br/>" + this.myArray);
}
Test.prototype.add = function() {
this.myArray.push(this.name);
}
var a = new Test('Scott');
a.add();
a.what();
var b = new Test('Smith');
document.writeln("<br/>" + b.myArray + " <= Check this one")
b.add()
b.what();
nobody touch b object array, why javascript engine get it from Class prototype why not it just take empty array belong to that object.
EDIT:
All the answers are correct, let change the type of property to primitive
function Test(name) {
this.name = name;
}
Test.prototype.primitive = 1;
Test.prototype.myArray = []; // I know if i move this to constructor it can resolve my problem
Test.prototype.what = function() {
document.writeln("<br/>" + this.myArray + " primitive:" +this.primitive);
}
Test.prototype.add = function() {
this.primitive++;
this.myArray.push(this.name);
}
var a = new Test('Scott');
a.add();
a.what();
var b = new Test('Smith');
document.writeln("<br/>" + b.myArray + " primitive:" +b.primitive +" <= Check this one now primtive is not shared")
b.add()
b.what();
So conclusion is all reference types attached to top prototype are shared to all instances and primitive datatypes like number are not.
why javascript engine get it from Class prototype why not it just take empty array belong to that object.
That's just how prototypical inheritance works. As you only assigned one array to the prototype object's property, instead of an array to every instance (like it happens if you create an assign in the constructor), there simply is no empty array belonging to the object and the property lookup goes to the prototype.
nobody touch b object array, why javascript engine get it from Class prototype why not it just take empty array belong to that object
That's the way prototype works in javascript. We have an object
and we have its prototype
.
An important fact here is that when you create a new object, it doesn't copy all the properties and methods of the prototype.
It actually have a reference to the prototype
object and the property / method resolution is performed dynamically.
For example, if you ask the object to return a myArray
property, javascript does this:
- Does
object
have myArray
? No (since you didn't declare this.myArray)
- Does
object.prototype
has myArray
? Yes
- Return
object.prototype.myArray
Now if you create two Test
objects, they actually have the same prototype and refer to the same prototype.myArray
property:
------------------
| Object a |
| | ---------------------
| name = 'Scott' | | |
| prototype ----|---------------> | prototype |
------------------ | |
| myArray = [] |
------------------ | |
| Object b | | |
| | | |
| name = 'Smith' | | |
| prototype ----|---------------> | |
------------------ ---------------------
Since both a
and b
have the same prototype
, they also refer to the same myArray
.
This way the modification of this array via a
or b
will change it for both objects.
Update: in the case when prototype
has a primitive value, it is still shared between a
and b
:
Test.prototype.primitive = 1
a = new Test();
a.primitive; // 1
b = new Test();
b.primitive; // 1
// Update prototype's primitive
Test.prototype.primitive += 1
// a and b objects refer to the updated value
a.primitive; // 2
b.primitive; // 2
But when you do something like a.primitive++
or, more explicitly, a.primitive = a.primitive + 1
, you actually create the primitive
property in the a
object and it doesn't refer to the prototype
anymore:
// Now a.primitive is actually created in the a object and
// does not refer to the prototype anymore
a.primitive++;
a.primitive; // 3
Test.prototype.primitive; // 2
b.prototype.primitive; // 2
// Now prototype primitive updates will only affect object b
Test.prototype.primitive += 2;
a.primitive; // 3
b.prototype.primitive; // 4
because you are adding to the Test
when you do Test.prototype.myArray
not to the instance of test. Just keep it in this.myArray
replace your code with
function Test(name) {
this.name = name; this.myArray = []; //observe this change
}
Test.prototype.what = function() {
console.log("<br/>" + this.myArray);
}
Test.prototype.add = function() {
this.myArray.push(this.name);
}
var a = new Test('Scott');
a.add();
a.what();
var b = new Test('Smith');
console.log("<br/>" + b.myArray + " <= Check this one")
b.add()
b.what();
prototypes in JavaScript are used as fallbacks.
Meaning that if the object in question doesn't have the requested member(method or property), the prototype of the current object is queried to find that member.
If it is not there the upper prototype is queried and this process is going up until it reaches the Object prototype Which is the base prototype in JavaScript.
Here is an example :
var test1,test2,test3;
Object.prototype.getInfo = function(){
return this.firstName + " - " + this.lastName;
}
function test1(){
this.firstName = "ham";
}
test2.prototype = test1;
function test2(){
this.lastName = "bam";
}
test3.prototype = test2;
function test3(){
return this.getInfo();
}
test1(); // at this level firstName property is available
test2(); // at this level firstName,lastName properties are available
test3(); // returns 'ham - bam' because the main prototype Object has the method getInfo and we have firstName,lastName from the previous prototypes.
When reaching the Object prototype, if the requested member still not found, an error is thrown.
Here is the jsfiddle example
Hope this hepls.