Prototype context |
Page 2 of 2
SolutionThe 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(){ and a lot of other definitions 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. PatternTo 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(){ 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(){ Now this does work - up to a point. If you try : 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(); 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. More Puzzles
<ASIN:059680279X> <ASIN:0470526912> <ASIN:1590597273> <ASIN:0596806752> |