tags:

views:

1049

answers:

7

Hello,

Is there any way to make "private" variables (those defined in the constructor), available to prototype-defined methods?

TestClass = function(){
    var privateField = "hello";
    this.nonProtoHello = function(){alert(privateField)};
};
TestClass.prototype.prototypeHello = function(){alert(privateField)};

This works:

t.nonProtoHello()

but this doesn't:

t.prototypeHello()

I'm used to defining my methods inside the constructor, but am moving away from that for a couple reasons.

thanks!

-Morgan

A: 

Thanks sktrdie,

That works, it would be nice not to have to create the this.accessPrivateField. If my "hello" function is defined inside the constructor, privateField is in the scope chain of the function, so I can treat privateField as I would a private field in java. It's a little more cumbersome to set up accessors (this.accessPrivateField), and then, privateField isn't really private any more. I know javascript isn't java, but I like java!

-Morgan

morgancodes
+7  A: 

No, there's no way to do it. That would essentially be scoping in reverse.

Methods defined inside the constructor have access to private variables because all functions have access to the scope in which they were defined.

Methods defined on a prototype are not defined within the scope of the constructor, and will not have access to the constructor's local variables.

You can still have private variables, but if you want methods defined on the prototype to have access to them, you should define getters and setters on the this object, which the prototype methods (along with everything else) will have access to.

Triptych
+2  A: 

see Doug Crockford's page on this. You have to do it indirectly with something that can access the scope of the private variable.

another example:

Incrementer = function(init) {
  var counter = init || 0;  // "counter" is a private variable
  this._increment = function() { return counter++; }
  this._set = function(x) { counter = x; }
}
Incrementer.prototype.increment = function() { return this._increment(); }
Incrementer.prototype.set = function(x) { return this._set(x); }

use case:

js>i = new Incrementer(100);
[object Object]
js>i.increment()
100
js>i.increment()
101
js>i.increment()
102
js>i.increment()
103
js>i.set(-44)
js>i.increment()
-44
js>i.increment()
-43
js>i.increment()
-42
Jason S
A: 

Thanks AdamB, Noooooo, no global variables!!!! Scary! I started to "get" why this wouldn't work as I posted the question, but was wondering if anyone had a clever technique to make js objects behave a little more like java w/regard to member variables. -Morgan

morgancodes
A: 

I think I'll probably just adopt the _treatThisAsPrivate convention

morgancodes
A: 

hi all of you guys i had the same problem but maybe a simple solution stay tuned i'm verifying all works good

see you soon

AngelsCrimes
A: 

you can use a prototype assignment within the constructor definition.

the variable will be visible to the prototype added method but all the instances of the functions will access the same SHARED variable.

es.:

function A()

{

var sharedVar = 0; this.local = ""

A.prototype.increment = function (lval)

{

if(lval)this.local = lval;


alert((++sharedVar) + " while this.p is still " + this.local);

}

}

var a = new A();

var b = new A();

a.increment("I belong to a");

b.increment("I belong to b");

a.increment();

b.increment();

i hope this can be usefull

AngelsCrimes