Reflection in JavaScript | | |
Hi,
I am working on an object that has a function that calls setInterval so
that it can have a function called repeatedly. Right now, to call the
function, you also have to provide the name of the instance that is
calling it (ie. notify.start('notify', 500)). Is there a way to have
the instance read its own name and provide it as a string so that the
only parameter required for the start function is the interval that it
should fire at? Also, is there a way for the object to keep a function
private but still have setInterval call it?
Thanks in advance
Chris Lieb | | | | re: Reflection in JavaScript
Chris Lieb wrote:[color=blue]
> I am working on an object that has a function that calls setInterval so
> that it can have a function called repeatedly. Right now, to call the
> function, you also have to provide the name of the instance that is
> calling it (ie. notify.start('notify', 500)). Is there a way to have
> the instance read its own name and provide it as a string so that the
> only parameter required for the start function is the interval that it
> should fire at?[/color]
This question and possible solutions have been explored here:
<http://groups.google.com/group/comp.lang.javascript/browse_frm/thread/3f544326c39ca6d9/49f961e7e57922f7>
Unfortunately yes, "this" implementation is borken in JavaScript (at
least from a outside point of view) and interpreter doesn't switch the
context back to the object for internal object methods in this
situation.
[color=blue]
> Also, is there a way for the object to keep a function
> private but still have setInterval call it?[/color]
Seems like private and protected scopes are not emulable in the
standard JavaScript. Just give your "protected" methods and fields some
criptic names like $_functionOne and hope to the best. :-( | | | | re: Reflection in JavaScript
On 21/11/2005 23:12, VK wrote:
[snip]
[color=blue][color=green]
>> Is there a way to have the instance read its own name and provide
>> it as a string so that the only parameter required for the start
>> function is the interval that it should fire at?[/color][/color]
No, because several identifiers may reference the same object, making
the notion of a single name nonsensical.
[snip]
[color=blue]
> Unfortunately yes, "this" implementation is borken in JavaScript
> [...][/color]
No, it isn't. The behaviour of the this operator is well-defined. That
isn't to say that other behaviour is sometimes wanted, but that's not
the same as broken.
[snip]
[color=blue][color=green]
>> Also, is there a way for the object to keep a function private but
>> still have setInterval call it?[/color][/color]
Yes and no.
The setTimeout and setInterval methods can take function references, so
it is possible to pass a reference to a function object that is private:
function MyObject() {
var self = this,
timer;
function callback() {
/* Use self to refer to instance of MyObject. */
}
this.start = function(period) {
timer = setInterval(callback, period);
};
}
However, some browsers only expect a string argument and will coerce the
function to a string (effectively call its toString method), evaluating
it in global scope. This can be dealt with relatively easily, but it
would mean exposing the private function so that it could be accessed
globally (though somewhat covertly):
function MyObject() {
var self = this,
timer;
function callback() {
/* Use self to refer to instance of MyObject. */
}
callback.toString = function() {
return 'MyObject[" $timers"][' + timer + ']()';
};
this.start = function(period) {
if(!timer) {
MyObject[' $timers'][
timer = setInterval(callback, period)
] = callback;
}
};
this.stop = function(period) {
if(timer) {
clearInterval(timer);
delete MyObject[' $timers'][timer];
timer = null;
}
};
}
MyObject[' $timers'] = {};
See <http://www.jibbering.com/faq/faq_notes/misc.html#mtSetTI> for a bit
more information regarding setTimeout/setInterval and function references.
[color=blue]
> Seems like private and protected scopes are not emulable in the
> standard JavaScript.[/color]
You were even given a link to articles explaining private scope (both
instance and static) yesterday, for goodness sake. Something resembling
protected scope is also feasible, but it's far more involved.
[snip]
Mike
--
Michael Winter
Prefix subject with [News] before replying by e-mail. | | | | re: Reflection in JavaScript
Michael Winter wrote:
[snip][color=blue]
> The setTimeout and setInterval methods can take function references, so
> it is possible to pass a reference to a function object that is private:
>
> function MyObject() {
> var self = this,
> timer;
>
> function callback() {
> /* Use self to refer to instance of MyObject. */
> }
>
> this.start = function(period) {
> timer = setInterval(callback, period);
> };
> }
>
> Mike
>
> --
> Michael Winter
> Prefix subject with [News] before replying by e-mail.[/color]
I tried what you suggested (I only have to support IE6, so I skipped
the second part that did the string stuff), but cannot fogure out how
to get it to work. I always get an error telling me that the object
does not support the method. Here is my relevant code:
function fader() {
// private variable initialization
var timer; // keep the intervel ID so we can stop it
var ref = this; // this instance of fader
// public function declarations
/*
* Start the fading
* @param _interval the time between each call to fade
*/
this.start = function(_interval) {
if (!timer) {
timer = window.setInterval(function(){ref.callback();}, _interval);
}
}
function callback() {
/* I'm not sure what goes here */
/* Perhaps ref.fade(); ? */
}
/*
* Stop the fading
*/
this.stop = function() {
if (timer) {
window.clearInterval(timer);
timer = null;
}
}
/*
* Perform the fading operation; to be called by timer
*/
this.fade = function() {
/* Function to be called by timer */
/* I want this function to be private */
}
}
I can see why callback() is not visible since it has no public name
declared, so I don't see how it is supposed to be visible to
setInterval.
Chris | | | | re: Reflection in JavaScript
Chris Lieb wrote:[color=blue]
> I only have to support IE6[/color]
If so than simply install the free Microsoft .NET Framework 1.1 (which
will update your JScript engine to JScript.Net)
and use
....
private this.methodName = function() {...}
.... | | | | re: Reflection in JavaScript
VK wrote:[color=blue]
> Chris Lieb wrote:[color=green]
> > I only have to support IE6[/color]
>
> If so than simply install the free Microsoft .NET Framework 1.1 (which
> will update your JScript engine to JScript.Net)
>
> and use
> ...
> private this.methodName = function() {...}
> ...[/color]
I'd love to, but I don't have the authority to roll out .NET to the
entire facility. The only machines that have .NET are our web servers,
and we don't even have VS .NET to take advantage of it, nor any ASP
..NET / C# / B# programmers. (OK, I'm kind of a C# programmer, but we
don't do .NET right now, so it's a moot point.)
Chris Lieb | | | | re: Reflection in JavaScript
On 22/11/2005 14:55, Chris Lieb wrote:
function Fader() {
var self = this,
timer;
function fade() {
/* If you need to refer to public properties of
* the Fader instance, use the self variable.
*/
}
this.start = function(interval) {
if(!timer) {
timer = setInterval(fade, interval);
}
};
this.stop = function(interval) {
if(timer) {
clearInterval(timer);
timer = null;
}
};
}
[snip]
[color=blue]
> function callback() {
> /* I'm not sure what goes here */
> /* Perhaps ref.fade(); ? */
> }[/color]
The callback function was a place holder. You said you wanted a private
function that could be called by setInterval, and this was it.
[snip]
[color=blue]
> I can see why callback() is not visible since it has no public name
> declared,[/color]
Yes, it's a inner (local) function, so only code within that outer
function (the constructor) or other inner functions may call it directly.
As the start and stop methods are defined within the constructor, they
are also able to access the callback function (the local variables, too)
because it appears in their scope chain. When they are added as
properties of the Fader instance, they will survive after the
constructor returns, forming a closure and maintaining their access to
these otherwise private variables.
[color=blue]
> so I don't see how it is supposed to be visible to setInterval.[/color]
A reference to that function is passed to setInterval. It doesn't /need/
to have access to the function through normal means because it was given
direct access to the function by something that /does/ have access.
[Analogy - skip if you don't need it]
Imagine three people, A, B, and C. Person A has something that C wants,
but A doesn't want to give it to her. So, C asks B to get it, and he
does. B then passes it to C.
In this code, the constructor function is person A; it has an inner
function that an external entity, C (setInterval), wants. The start
method (B) has access to both the 'thing' belonging to A, and to C, so
it passes it between the two.
[/Analogy]
Mike
--
Michael Winter
Prefix subject with [News] before replying by e-mail. | | | | re: Reflection in JavaScript
Michael Winter wrote:
[snip][color=blue]
> A reference to that function is passed to setInterval. It doesn't /need/
> to have access to the function through normal means because it was given
> direct access to the function by something that /does/ have access.
>
> [Analogy - skip if you don't need it]
> Imagine three people, A, B, and C. Person A has something that C wants,
> but A doesn't want to give it to her. So, C asks B to get it, and he
> does. B then passes it to C.
>
> In this code, the constructor function is person A; it has an inner
> function that an external entity, C (setInterval), wants. The start
> method (B) has access to both the 'thing' belonging to A, and to C, so
> it passes it between the two.
> [/Analogy]
>
> Mike[/color]
I guess that I am just too used to full blown object oriented
programming languages where I can just create a timer inside the class
and keep all of the implementation details from the public interface,
only exposing start() and stop(). After reading all of this, I guess
that there is no way to make the method completely private and not
expose any way to manually call it to the public. Thanks for the help.
Chris Lieb | | | | re: Reflection in JavaScript
On 22/11/2005 20:27, Chris Lieb wrote:
[snip]
[color=blue]
> I guess that I am just too used to full blown object oriented
> programming languages where I can just create a timer inside the class
> and keep all of the implementation details from the public interface,
> only exposing start() and stop().[/color]
That's precisely what the code I posted does (though there are no
classes in ECMAScript). Only the start and stop methods can be called by
client code.
[snip]
Mike
--
Michael Winter
Prefix subject with [News] before replying by e-mail. | | | | re: Reflection in JavaScript
JRS: In article <Sntgf.13274$Lw5.7366@text.news.blueyonder.co.uk >,
dated Tue, 22 Nov 2005 00:12:34, seen in news:comp.lang.javascript,
Michael Winter <m.winter@blueyonder.co.uk> posted :[color=blue]
>On 21/11/2005 23:12, VK wrote:
>
>[snip]
>[color=green][color=darkred]
>>> Is there a way to have the instance read its own name and provide
>>> it as a string so that the only parameter required for the start
>>> function is the interval that it should fire at?[/color][/color]
>
>No, because several identifiers may reference the same object, making
>the notion of a single name nonsensical.[/color]
But ISTM that any of the names might do.
If a function is passed as a parameter to a routine, the routine can
determine the original name of the function by processing
function.toString().
--
© John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v4.00 IE 4 ©
<URL:http://www.jibbering.com/faq/> JL/RC: FAQ of news:comp.lang.javascript
<URL:http://www.merlyn.demon.co.uk/js-index.htm> jscr maths, dates, sources.
<URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/jscr/&c, FAQ items, links. | | | | re: Reflection in JavaScript
Michael Winter wrote:[color=blue]
> On 22/11/2005 20:27, Chris Lieb wrote:
>
> [snip]
>[color=green]
> > I guess that I am just too used to full blown object oriented
> > programming languages where I can just create a timer inside the class
> > and keep all of the implementation details from the public interface,
> > only exposing start() and stop().[/color]
>
> That's precisely what the code I posted does (though there are no
> classes in ECMAScript). Only the start and stop methods can be called by
> client code.
>
> [snip]
>[/color]
I guess that I just needed a good night's rest to let this soak into my
head. All I ended up having to do was declare the fade fuction as
function fade() {....}
instead of
this.fade = function() {....}
and change the setInterval from
timer = setInterval(function(){self.fade();}, _interval)
to
timer = setInterval(fade, _interval)
I didn't have to use self to reference member variables in the fade
function, however. When I tried, IE gave me an error about the
variable having no value or something of that nature. The script seems
to work in both IE and Gecko, so I am content at this point.
Thanks
Chris Lieb |  | Similar JavaScript / Ajax / DHTML bytes | | | /bytes/about
We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights.
Get the best answers to your questions from over 226,295 network members.
|