473,396 Members | 1,797 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

evaluation context of event handler string


What is the evaluation context of the setTimeout args below? I have a
separate Timer instance for each sprite in my program. As coded,
"this.Clock" doesn't work. Thanks ahead for any advice.

Albert

/*================================================= ===
Timer.js
================================================== ==*/

function Timer(_sprite, _interval) {
var sprite = _sprite;
var interval = _interval;
var isRunning = false;
var timeoutID = false;
this.Clock = function() { // called after setTimout interval
if (isRunning) {
isRunning = sprite.OnClockTick();
if (isRunning)
timeoutID = window.setTimeout("this.Clock()", interval);
else
this.Stop();
}
}
this.Stop = function() {
if (timeoutID) {
window.clearTimeout(timeoutID);
timeoutID = false;
};
isRunning = false;
}
this.SetInterval = function(_interval) {
this.Stop();
interval = _interval;
isRunning = true;
timeoutID = window.setTimeout("this.Clock()",interval);
}
this.Continue = function() {
if (!isRunning) {
isRunning = true;
timeoutID = window.setTimeout("this.Clock()",interval);
}
}
}
--
Don't you see that the whole aim of Newspeak is to narrow the range of
thought? In the end we shall make thoughtcrime literally impossible,
because there will be no words in which to express it.
-- George Orwell, 1984

Jul 20 '05 #1
9 2910
On Sat, 20 Sep 2003 13:05:55 -0500
Albert Wagner <al******@tcac.net> wrote:
<snip>

Never mind. I removed "this." from Clock and setTimeout(Clock,
interval) and this works. I just got my copy of O'Reilly's book
"JavaScript - The Definitive Guide (4th Ed.)" and they had an example;
so it's already begun to pay for itself :-)

Clock = function() { // called after setTimout interval
if (isRunning) {
isRunning = sprite.OnClockTick();
if (isRunning)
timeoutID = window.setTimeout(Clock, interval);
else
this.Stop();
}
}
<snip>
--
Don't you see that the whole aim of Newspeak is to narrow the range of
thought? In the end we shall make thoughtcrime literally impossible,
because there will be no words in which to express it.
-- George Orwell, 1984

Jul 20 '05 #2
JRS: In article <20******************************@tcac.net>, seen in
news:comp.lang.javascript, Albert Wagner <al******@tcac.net> posted at
Sat, 20 Sep 2003 15:32:29 :-
On Sat, 20 Sep 2003 13:05:55 -0500
Albert Wagner <al******@tcac.net> wrote:
<snip>

Never mind. I removed "this." from Clock and setTimeout(Clock,
interval) and this works. I just got my copy of O'Reilly's book
"JavaScript - The Definitive Guide (4th Ed.)" and they had an example;
so it's already begun to pay for itself :-)

Clock = function() { // called after setTimout interval
if (isRunning) {
isRunning = sprite.OnClockTick();
if (isRunning)
timeoutID = window.setTimeout(Clock, interval);
else
this.Stop();
}
}
<snip>


Obviously O'Reilly did not read this newsgroup for long enough before
printing that, or you missed what they should also have written. The
comment in the code is AFAICS absolutely accurate. But, if
interval=1000, the function will not be started once every second. The
average interval will be a little over 1027 ms in Win98, and a little
over 1005 ms in XP, IIRC.

Via the newsgroup FAQ :
<URL:http://www.merlyn.demon.co.uk/js-date1.htm#TaI> refers.
<URL:http://www.merlyn.demon.co.uk/js-date3.htm#RC> shows it fixed.

--
© John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v4.00 IE 4 ©
<URL:http://jibbering.com/faq/> Jim Ley's FAQ for news:comp.lang.javascript
<URL:http://www.merlyn.demon.co.uk/js-index.htm> JS maths, dates, sources.
<URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/JS/&c., FAQ topics, links.
Jul 20 '05 #3
On Sun, 21 Sep 2003 21:34:11 +0100
Dr John Stockton <sp**@merlyn.demon.co.uk> wrote:
<snip>

Obviously O'Reilly did not read this newsgroup for long enough before
printing that, or you missed what they should also have written. The
comment in the code is AFAICS absolutely accurate. But, if
interval=1000, the function will not be started once every second.
The average interval will be a little over 1027 ms in Win98, and a
little over 1005 ms in XP, IIRC.

<snip>

Thanks for the reply, John. The code was mine, not O'Reilly's. Their
example(s) in the book simply gave me a clue as to how to fix my code.
Actually, for my purposes, it still doesn't work. I was attempting to
have separate timers for each sprite; Clock is a global, and therefore
with two timers I had one instance of Clock overriding the other. I am
refactoring the code for a different solution now, using setInterval
rather than setTimeout.
--
Don't you see that the whole aim of Newspeak is to narrow the range of
thought? In the end we shall make thoughtcrime literally impossible,
because there will be no words in which to express it.
-- George Orwell, 1984

Jul 20 '05 #4
"Albert Wagner" <al******@tcac.net> wrote in message
news:20030920130555.6744455f.al******@tcac.net...
What is the evaluation context of the setTimeout args below? I have
a separate Timer instance for each sprite in my program. As coded,
"this.Clock" doesn't work. Thanks ahead for any advice.


String arguments passed to setTimeout/Interval are evaluated in the
global context.

Function reference arguments are passed as a reference to a function and
so property accessors that refer to a function as a property of an
object will not be executed as a method of the object but just a
function executing in the global context. The exception being inner
functions which will be executed in the global context (this == the
global object) but as inner functions they will still be able to
reference local variables and parameters of their outer function(s if
nested).

The passing of references to inner functions is the easiest method of
associating an argument to setTimeout/Interval with an object instance:-

MyObject.prototype.exampeFunc(){
var self = this;
function innerFunction(){
if(self.anyProperty){
self.anyMethod();
}
}
setTimeout(innerFunction, 1000);
//innerFunction (no parenthesises on function reference)
//is called in 1000 milliseconds (ish) and can refer to the
//- this - from this execution context as - self - (the outer
//function local variable)
}

Passing function reference arguments to setTimeout/Interval is not
supported in some older browsers (IE 4 and Opera 5 at least). If that is
important then there is a workaround that involves providing the
function that is passed with a custom toString method (google search
c.l.j. for explanations and examples).

Richard.
Jul 20 '05 #5
I love this way of setting event handlers and setTimeout.
The funny thing is I had no clue about the syntax as it
applied to setTimeout until I read Douglas Crockford's
(thanks Douglas!) response to "settimeout problem" (Sept
18) and now I've seen it several times. This is going to
save me a lot of quote marks, I can already tell.
I want to put an onresize handler onto every cell in a
table. My resizeHandler function insists on knowing
which TD a given invokation is associated with.
We should actually have a setTimeout, too, since IE is
a bit of a laggard in this arena:

for each myCell in the table we can do:

myCell.onresize = function () {
var tmpVar = this;
setTimeout(function() {resizeHandler(tmpVar)}, 20)}

This seems to be working. But I am really suspicious
of that tmpVar. Can someone explain to me whether I'm
getting lucky or whether that tmpVar is safe from being
overwritten if other cells are getting resized. I.e. what is
that tmpVar bound to?
In the interests of better understanding, I'd like to change
the scenario a bit. This time resizeHandler2 only wants to
have handed to it the explicit rowIndex and cellIndex of the
cell that's responsible for its invokation.

So one might imagine the setup proceeding as follows:
for (var i=myTable.rows.length-1;i>=0;i--)
for (var j=myTable.rows[i].cells.length-1;j>=0;j--)
myTable.rows[i].cells[j].onresize = function () {
setTimeout(function () {resizeHandler2(i, j)}, 20)}

This is incorrect, because i and j are not the current values
but rather future values and get passed in as -1 when invoked.
How can I fix this up, so that what I pass in is the i and j
at the time of the function construction and not execution
(without introducing strings. The point being that I want to
know whether I can combine the two approaches)?

Thanks,
Csaba Gabor from New York

"Richard Cornford" <ri*****@litotes.demon.co.uk> wrote in message news:bk**********@hercules.btinternet.com...
"Albert Wagner" <al******@tcac.net> wrote in message
news:20030920130555.6744455f.al******@tcac.net...
What is the evaluation context of the setTimeout args below? I have
a separate Timer instance for each sprite in my program. As coded,
"this.Clock" doesn't work. Thanks ahead for any advice.


String arguments passed to setTimeout/Interval are evaluated in the
global context.

Function reference arguments are passed as a reference to a function and
so property accessors that refer to a function as a property of an
object will not be executed as a method of the object but just a
function executing in the global context. The exception being inner
functions which will be executed in the global context (this == the
global object) but as inner functions they will still be able to
reference local variables and parameters of their outer function(s if
nested).

The passing of references to inner functions is the easiest method of
associating an argument to setTimeout/Interval with an object instance:-

MyObject.prototype.exampeFunc(){
var self = this;
function innerFunction(){
if(self.anyProperty){
self.anyMethod();
}
}
setTimeout(innerFunction, 1000);
//innerFunction (no parenthesises on function reference)
//is called in 1000 milliseconds (ish) and can refer to the
//- this - from this execution context as - self - (the outer
//function local variable)
}

Passing function reference arguments to setTimeout/Interval is not
supported in some older browsers (IE 4 and Opera 5 at least). If that is
important then there is a workaround that involves providing the
function that is passed with a custom toString method (google search
c.l.j. for explanations and examples).

Richard.

Jul 20 '05 #6
"Csaba2000" <ne**@CsabaGabor.com> writes:
for each myCell in the table we can do:

myCell.onresize = function () {
var tmpVar = this;
setTimeout(function() {resizeHandler(tmpVar)}, 20)}

This seems to be working. But I am really suspicious
of that tmpVar. Can someone explain to me whether I'm
getting lucky or whether that tmpVar is safe from being
overwritten if other cells are getting resized.
It is safe.

You declare tmpVar as a local variable. That means that a new variable
is created for each call to the (anonymous) function it lives in.
The inner function expression evaluates to a *closure*. It is a function
value that includes references to all the variables that it uses.

That means that a reference to the local variable survives longer than
the call to the function it lives in. That can be confuzing to people
used to languages like C and C++, where local variables are created on
the stack and removed when the function returns. In this case, it is
just what you need!
I.e. what is that tmpVar bound to?
For each call, it is bound to a new location, and the function inside
is also new each time.
In the interests of better understanding, I'd like to change
the scenario a bit. This time resizeHandler2 only wants to
have handed to it the explicit rowIndex and cellIndex of the
cell that's responsible for its invokation.

So one might imagine the setup proceeding as follows:
for (var i=myTable.rows.length-1;i>=0;i--)
for (var j=myTable.rows[i].cells.length-1;j>=0;j--)
myTable.rows[i].cells[j].onresize = function () {
setTimeout(function () {resizeHandler2(i, j)}, 20)}

This is incorrect, because i and j are not the current values
but rather future values and get passed in as -1 when invoked.
Correct. The inner function contains references to the same instances
of the variables i and j. You can see a variable "x" as a way to
reference a *location*, and that location can contain a *value*.
The function closure remembers the association from variable name
to location, not the value currently in that location. The value
is only looked up when the code containing the variable is executed.
How can I fix this up, so that what I pass in is the i and j
at the time of the function construction and not execution
(without introducing strings. The point being that I want to
know whether I can combine the two approaches)?


You need to create new locations for each inner function. The simplest
(and perhaps the only) way is to put it inside a function. Chang the
last line to:

setTimeout(
function(i,j) {return function () {resizeHandler2(i, j);};}(i,j),
20)}

By wrapping the innner function in another function, we make the i and
j be local variables that are unique to each call. The arguments are
passed as values, so the new variables have the current *values* of
the outer i and j.
We need not call the new variables i and j, they could be called anything:

function(foo,bar) {return function () {resizeHandler2(foo,bar);};}(i,j)

and we could create them with "var" instead of as arguments:

function() {var x=i,y=j;return function (){resizeHandler2(x,y);};}()

The outer function is called immediately, so the code is executed. The
new local variables gets the *values* of i and j. The reference to
these new variables are kept in the returned function.

Behind all of this is the notion of a "lvalue", short for "left value".

How do you evaluate a variable. What is the meaning of "x" in a program.
There are two answers, depending on where "x" occurs, whether it is on
the left or right side of an assignment.

When you write an assignment
x = y;
we have two variables. The one on the left hand side of the assignment
is the variable having its value changed. What happens is:

Find value of right hand side:
Look up "y" in the variable list to find the location it refers to.
Find the value stored in that location.
Look up "x" in the variable list to find the location it refers to.
Store the value from before in that location.

The right hand side is evaluted for its value. The left hand side is
evaluted for its location (it's "l-value"), not its right-value (which
is what we normally call its *value*).

Closures retain the lvalue of a variable.

Hope this helps.
/L
--
Lasse Reichstein Nielsen - lr*@hotpop.com
Art D'HTML: <URL:http://www.infimum.dk/HTML/randomArtSplit.html>
'Faith without judgement merely degrades the spirit divine.'
Jul 20 '05 #7
Lasse,

thank you, Thank You, THANK YOU for a super fantastic
post. I had not thought about this idea of returning a function
from a function. Very nice. I learned so much about this new
way (for me) of looking at these calls. Thanks again for making
things so clear.

Deep regards from New York,
Csaba
Jul 20 '05 #8
This thread is awesome.

Can you call what you did in your example a functor?

I had never thought of doing functors in javascript.

Thanks Lasse! Thanks Csaba2000!
Jul 20 '05 #9
b0*****@yahoo.com (asdf asdf) writes:
Can you call what you did in your example a functor?


That depends what you mean by "functor". It is not a functor in the
sense of Standard-ML. There a functor is a mapping from a structure to
a structure (where a structure is a name space/module).

This is just a function that returns a function, a simple higher order
function.

/L
--
Lasse Reichstein Nielsen - lr*@hotpop.com
Art D'HTML: <URL:http://www.infimum.dk/HTML/randomArtSplit.html>
'Faith without judgement merely degrades the spirit divine.'
Jul 20 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

18
by: Christopher W. Douglas | last post by:
I am writing a VB.NET application in Visual Studio 2003. I have written a method that handles several events, such as closing a form and changing the visible status of a form. I have some code...
0
by: VP | last post by:
G'day folks, well i am attempting to get an understanding on how to create the menuitems in a context menu on the fly. So far I have managed to actually achieve the menu items being created for...
1
by: Dennis | last post by:
I'm using VS 2003 my project uses COM interop and the Tao Framework. I have a custom control derived from UserControl. It implements many functions similar to the Tao's SimpleOpenGLControl, for...
4
by: Don Peters | last post by:
I can't seem to find an answer to this problem in spite of many searches. I have a VB.NET program that has a context menu popup event. In it I associate some menu items with their events, as...
0
by: Demetri | last post by:
I have created a web control that can be rendered as either a linkbutton or a button. It is a ConfirmButton control that allows a developer to force a user to confirm if they intended to click it...
1
by: Roy | last post by:
From the MS site: NAME: ClientScriptManager.GetCallbackEventReference (Control, String, String, String) DESCRIPTION: Obtains a reference to a client-side function that, when invoked, initiates a...
2
by: Paul E Collins | last post by:
A context menu is created in the scope of the RightClick event, but it continues to be displayed after that event handler terminates - i.e. after it has gone out of scope. The code works correctly,...
5
by: james | last post by:
Hello, I am having a little trouble creating an event handler for a context menu toolstripmenuitem. I've seen various tutorials and so on, but I keep getting a bit stuck! So far I have a second...
2
by: MCM | last post by:
I'm working on a plotting control. The plotting control will have a context menu with basic commands for "scaling", "zooming", etc. Is there a way that, from the parent form, I can add more...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.