Prototype context
Article Index
Prototype context
Solution

Solution

The problem is caused by the prototype mechanism not really being an object oriented way of sharing code.  The reason that this doesn't work is that if a method is called on the prototype object then this is correctly set to reference the context of the instance making the call:

MyConstructor = function(){
var x = "ABC";
and a lot of other definitions
}
MyConstructor.prototype.getX=function(){}
MyObj=new MyConstructor();
alert(MyObj.getX());

Hence in the prototype this.y evaluates to MyObj.y say. However a the prototype object's functions do not execute in the scope provided by the constructor's closure. That is in the prototype object referring to a variable just as x either resolves to a local variable defined in the function or a global variable if that doesn't exist. That is the any functions defined on the prototype object are given any closures necessary to capture local variables that are in scope when the function is defined on the prototype object not in the constructor function.

To put this more simply - prototype methods do not have access to private variables belonging to the object but constructor methods do.

Pattern

To avoid this problem simply don't try to implement private variables for methods defined on the prototype object. However, this seems like a bit restriction.

One possible alternative solution is not to use the prototype mechanism unless it is absolutely necessary. Most objects in a JavaScript program are only instantiated a small number of times. In such cases the memory overhead of having multiple copies of functions isn't worth worrying about. Only if an object is going to be instantiated thousands of times do you need to be concerned  - but in such cases the object is usually dominated by data rather than methods. So avoid the prototype mechanism and use other ways that are more suited to JavaScript for inheritance.

Before leaving the subject it is probably worth pointing out that adding private variables to the prototype object doesn't help the situation for a very simply reason - the prototype object is shared. Let's look at two ways that don't work!

The first is to simply use a function to create a closure for the function that we really want. For example:

MyConstructor.prototype.getX=function(){
var x="123";
return function(){return x;}();
}

In this case the closure is provided to the anonymous function that is evaluated as the return result. If you try this out:

alert(MyObj.getX());

you will discover that 123 is displayed. However, the private variable x is only accessible to the anonymous function and it is created each time the getX function is called - i.e. it has no memory. This is interesting but fairly useless!

The second attempt uses a constructor function to create the prototype object. For example:

MyProtConstruct=    function(){
var x=0;
this.count=function(){
return x++;
}
}
MyConstructor.prototype=new MyProtConstruct();

Now this does work - up to a point. If you try :

alert(MyObj.count());
alert(MyObj.count());

you will find that it does indeed count the number of times the function is called. The variable x is indeed private and it isn't created each time the function is called - unfortunately because of the prototype mechanism there is only one copy of the count method and one copy of the private variable shared between all of the instances. For example if you try:

MyObj=new MyConstructor();
MyObj2=new MyConstructor();
alert(MyObj.count());
alert(MyObj.count());
alert(MyObj2.count());

you will discover that the sequence displayed is 0, 1, 2 and not 0, 1, 0 which is what it would be if MyObj2 had its own private variable and not a shared copy of x.

The best advice is to keep it simple.

Put private instance variables in the constructor and just accept the fact that the prototype mechanism doesn't support private variables.

Banner

More Puzzles

Sharpen Your Coding Skills
Towers Of Hanoi Mutants

Towers of Hanoi is a classic puzzle and is often used to illustrate the idea of recursion. Here you are challenged to find solutions to some variations, after first explaining the original version.


Sharpen Your Coding Skills
Sharpen your Coding Skills - Elevator Puzzle

Introducing Melvin and Bugsy, characters who figure in a series of challlenges from Joe Celko. Sharpen your coding skills with puzzles that will both amuse and torment you.


C#
Programmer Puzzle - Class and struct

This C# puzzle shouldn't be difficult as long as you are secure in your understanding of class and structs. See if you can spot the danger as soon as you read it.


Other Articles


<ASIN:059680279X>

<ASIN:0470526912>

<ASIN:1590597273>

<ASIN:0596806752>