Replacing a private function an keeping access to private variables

G

Gregor Kofler

How can I access a private variable when replacing a private function,
which originally had access to this variable, with another one? Or is it
just not possible?

Example:

function foo() {
var privateVar = 42;

var privateFunc = function() {
alert(privateVar);
}

return {
replacePF: function(f) { privateFunc = f; }
}
}

var obj = foo();
obj.privateFunc(); // 42

obj.replacePF(function() { alert("The answer is "+privateVar); }
obj.privateFunc(); // privateVar is undefined


Gregor
 
T

Tiago Albineli Motta

How can I access a private variable when replacing a private function,
which originally had access to this variable, with another one? Or is it
just not possible?

Example:

function foo() {
   var privateVar = 42;

   var privateFunc = function() {
     alert(privateVar);
   }

   return {
     replacePF: function(f) { privateFunc = f; }
   }

}

var obj = foo();
obj.privateFunc(); // 42

obj.replacePF(function() { alert("The answer is "+privateVar); }
obj.privateFunc(); // privateVar is undefined

Gregor

--http://photo.gregorkofler.at::: Landschafts- und Reisefotografiehttp://web.gregorkofler.com ::: meine JS-Spielwiesehttp://www.image2d.com     ::: Bildagentur für den alpinen Raum

I think it's not possible because in the example the obj returned by
the function foo() doesn't have the function "privateFunc". In fact,
your first use of privateFunc doesnt work too. The message that i
have, if i remove the lasts lines is:

Error: obj.privateFunc is not a function

And if a add again the lasts lines i receive the error "privateVar is
undefined" because the last line is missing a parentesis ")", look:

your: obj.replacePF(function() { alert("The answer is
"+privateVar); } // privateVar is undefined
correctef: obj.replacePF( function() { alert("The answer is
"+privateVar); } );

The error was like:

Error: missing ) after argument list
Line: 28, Column: 27
Source Code:
// privateVar is undefined

The message "privateVar is undefined" were shown because the comments
after the syntatic error.

http://programandosemcafeina.blogspot.com
 
G

Gregor Kofler

Tiago Albineli Motta meinte:
I think it's not possible because in the example the obj returned by
the function foo() doesn't have the function "privateFunc". In fact,
your first use of privateFunc doesnt work too.

Sigh. I shouldn't post - untested - examples at 2 o' clock in the
morning... The public method for accessing the private function is of
course missing (plus the parenthesis). I hope this one's better now:

function foo() {
var privateVar = 42;

var privateFunc = function() {
alert(privateVar);
};

return {
replacePF: function(f) { privateFunc = f; },
accessPF: function() { privateFunc(); }
};
}

var obj = foo();
obj.accessPF(); // 42

obj.replacePF(function() {
window.alert("The answer is "+privateVar);
});
obj.accessPF(); // privateVar is undefined

Gregor
 
T

Thomas 'PointedEars' Lahn

Gregor said:
function foo() {
var privateVar = 42;

var privateFunc = function() {
alert(privateVar);
};

return {
replacePF: function(f) { privateFunc = f; },
accessPF: function() { privateFunc(); }
};
}

var obj = foo();

I am curious, why did you choose to use a factory instead of a constructor?
obj.accessPF(); // 42

obj.replacePF(function() {
window.alert("The answer is "+privateVar);
});
obj.accessPF(); // privateVar is undefined

It's a closure and `privateVar' in privateFunc() is bound to the execution
context of foo(), in which `privateFunc' was declared a variable. However,
the function expression in the obj.replacePF() call creates a closure in
which `privateVar' is bound to the execution context in which the call is
executed and the anonymous Function object is created, and in which scope
chain no object has such a property.

ISTM the only way to do this is to have a public method that returns
`privateVar', which would become "protected" through this: Either

function foo()
{
var privateVar = 42;

var privateFunc = function() {
window.alert(privateVar);
};

return {
getPrivateVar: function() { return privateVar; },
replacePF: function(f) { privateFunc = f; },
accessPF: function() { privateFunc(); }
};
}

var obj = foo();

or

function Foo()
{
var privateVar = 42;

var privateFunc = function() {
window.alert(privateVar);
};

this.getPrivateVar = function() { return privateVar; };
this.replacePF = function(f) { privateFunc = f; };
this.accessPF = function() { privateFunc(); };
}

var obj = new Foo();

and then

// 42
obj.accessPF();

obj.replacePF(function() {
window.alert("The answer is " + obj.getPrivateVar());
});

// "The answer is 42"
obj.accessPF();

(It's the usual simple getter and setter implementation as it is.)


HTH

PointedEars
 
G

Gregor Kofler

Thomas 'PointedEars' Lahn meinte:
I am curious, why did you choose to use a factory instead of a constructor?

I've started switching from constructor instantiation to a factory like
pattern after reading Crockfords new book, and realizing that I tend to
have objects with a meager amount of public properties, but lots of
private functions. On the other hand I do need a factory occassionally.
Since I try to avoid mixing the patterns, I stick to factories most of
the time now.
It's a closure and `privateVar' in privateFunc() is bound to the execution
context of foo(), in which `privateFunc' was declared a variable. However,
the function expression in the obj.replacePF() call creates a closure in
which `privateVar' is bound to the execution context in which the call is
executed and the anonymous Function object is created, and in which scope
chain no object has such a property.

Yep, I know the reason, why I can't access it this way, but I was rather
tired yesterday evening and had this feeling that missed something.
ISTM the only way to do this is to have a public method that returns
`privateVar', which would become "protected" through this

[snip]

Ok, that's the approach I already use.

Sort of.

Gregor
 
A

agendum97

How can I access a private variable when replacing a private function,
which originally had access to this variable, with another one? Or is it
just not possible?

If possible for your scenario, you could potentially use eval for
this. For example:


function MyClass(val)
{
var printIt = function () { window.alert("1:" + val); }
this.callPrintIt = function () { printIt(); }
this.setPrintIt = function (evalStr) { eval("printIt = " +
evalStr); }
}

var c = new MyClass("test");
c.callPrintIt();
c.setPrintIt("function () { window.alert(\"2:\" + val); }");
c.callPrintIt();


Thanks
 
G

Gregor Kofler

(e-mail address removed) meinte:
If possible for your scenario, you could potentially use eval for
this.

No I never thought of eval() - for a lot of reasons. Anyway, it might
work in this example, but not in my real life problem, where a mousemove
listener is replaced by a custom function, which should still be able to
access the "hidden" variables of the object.

Gregor
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,731
Messages
2,569,432
Members
44,832
Latest member
GlennSmall

Latest Threads

Top