1

wish to extend define and/or execute new methods against an object using its private methods - exactly as if I were to define the method within the original declaration - except these new methods apply only to this object to be executed one time, not to the Klass itself.

for example:

var Klass = function() {
        var privateFn = function() { return 15 };
        this.publicFn1 = function() { return privateFn()+1; };
}

var k = new Klass();
console.log( k.publicFn1() );  // prints 16

suppose I wish to create and/or execute a new method on Klass, sum2(), that will add 2 to the privateFn.

have tried the brain-dead

k.publicFn2 = function() { return privateFn()+2 }
console.log( k.publicFn2() );

and it makes perfect sense that it does not work, but what does?

as a note, since functions are very long, attempting to maintain the syntax of privateFn() rather than self.privateFn() - this might be asking too much, but one hopes.

Russ Clarke
  • 17,511
  • 4
  • 41
  • 45
cc young
  • 18,939
  • 31
  • 90
  • 148

2 Answers2

4

There is no such thing as private in ECMAScript

var Klass = function() {
        var privateFn = function() { return 15 };
        this.publicFn1 = function() { return privateFn()+1; };
}

privateFn is a local variable which publicFn1 has access to due to scoping rules (and closures).

You cannot access privateFn outside the scope of function Klass

If you want to access privateFn outside the scope of function Klass then you have to expose it through a proxy or inject it further up the scope chain.

A proxy would be something like

this._private = function() {
  return privateFn;
}

Injecting further up the scope chain would be something like

var Klass = function() {
    var privateFn = function() { return 15 };
    this.publicFn1 = function() { return privateFn()+1; };
    this.uid = Klass.uid++;
    Klass.instances[this.uid] = {
        privateFn: privateFn
    };
}
Klass.uid = 0;
Klass.instances = [];

k.publicFn2 = function() { return Klass.instances[this.uid].privateFn()+2 }

Both are ugly.

The reason they are ugly is because you are emulating classical OO

Please use prototypical OO instead.

Shameless prototypical OO plug

Community
  • 1
  • 1
Raynos
  • 166,823
  • 56
  • 351
  • 396
1

Javascript is a prototype-based object-oriented language. That means if you wish to user instance-specific variables, you can do it by extending the prototype object of that object. Using it any other way is unnatural and leads to problems such as yours that require an extreme hack to overcome. Why not just use the language as it was intended?

The correct structure of your code would be more like the following:

function Klass(nr) {
    this.nr = nr;
};

Klass.prototype.publicFn = function() {
    alert(this.nr);
};

var inst = new Klass(13);
inst.publicFn();

There are no private functions in JS and there won't be. You can "hack" the similar effect, but at the cost of either hacking something on your own or using other libraries.

It makes little sense to try to bend the language to suit you. Instead you should learn the language as it is.

zatatatata
  • 4,761
  • 1
  • 20
  • 41
  • quite agree on using "language as it is", but more than once javascript has pleasantly surprised me. ;) – cc young Jul 18 '11 at 11:59
  • instance specific variables dont live on the prototype. Prototype methods live on the prototype. Properties/variables/value on the prototype are shared by all objects that have that prototype in the chain and are not instance specific. – Raynos Jul 18 '11 at 12:05
  • Maybe the wording wasn't so good, but what I meant was that you can use this.variable inside prototyped functions when you have any number of instances, where the this.variable is instance specific and can be different in every single one. – zatatatata Jul 18 '11 at 12:14