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
Programmer Puzzle - Hermit Boxes

Can you program a solution to this puzzle  in which you place 3D boxes on a 2D grid to prevent your opponent being able to make a legal move? Let's hear what the team at International Storm Door  [ ... ]


PHP
The Missing PHP Global

A global variable is a global variable and that's all there is to it. But if you write PHP code to be used by other people, you might want to consider that this isn't always the case. Can you see wher [ ... ]


C#
Overriding Problems A C# Puzzle

Objects are indispensable but exactly how a language implements them and makes them available to the programmer matters. Sometimes the class-based approach complete with inheritance makes things compl [ ... ]


Other Articles


<ASIN:059680279X>

<ASIN:0470526912>

<ASIN:1590597273>

<ASIN:0596806752>



 
 

   
RSS feed of all content
I Programmer - full contents
Copyright © 2014 i-programmer.info. All Rights Reserved.
Joomla! is Free Software released under the GNU/GPL License.