evaluation context of event handler string

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Albert Wagner

    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.OnClockT ick();
    if (isRunning)
    timeoutID = window.setTimeo ut("this.Clock( )", interval);
    else
    this.Stop();
    }
    }


    this.Stop = function() {
    if (timeoutID) {
    window.clearTim eout(timeoutID) ;
    timeoutID = false;
    };
    isRunning = false;
    }


    this.SetInterva l = function(_inter val) {
    this.Stop();
    interval = _interval;
    isRunning = true;
    timeoutID = window.setTimeo ut("this.Clock( )",interval) ;
    }


    this.Continue = function() {
    if (!isRunning) {
    isRunning = true;
    timeoutID = window.setTimeo ut("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

  • Albert Wagner

    #2
    Re: evaluation context of event handler string

    On Sat, 20 Sep 2003 13:05:55 -0500
    Albert Wagner <alwagner@tcac. net> wrote:
    <snip>

    Never mind. I removed "this." from Clock and setTimeout(Cloc k,
    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.OnClockT ick();
    if (isRunning)
    timeoutID = window.setTimeo ut(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

    Comment

    • Dr John Stockton

      #3
      Re: evaluation context of event handler string

      JRS: In article <20030920153229 .5f416b08.alwag ner@tcac.net>, seen in
      news:comp.lang. javascript, Albert Wagner <alwagner@tcac. net> posted at
      Sat, 20 Sep 2003 15:32:29 :-[color=blue]
      >On Sat, 20 Sep 2003 13:05:55 -0500
      >Albert Wagner <alwagner@tcac. net> wrote:
      ><snip>
      >
      >Never mind. I removed "this." from Clock and setTimeout(Cloc k,
      >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.OnClockT ick();
      > if (isRunning)
      > timeoutID = window.setTimeo ut(Clock, interval);
      > else
      > this.Stop();
      > }
      > }
      ><snip>[/color]

      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.demo n.co.uk/js-date1.htm#TaI> refers.
      <URL:http://www.merlyn.demo n.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.demo n.co.uk/js-index.htm> JS maths, dates, sources.
      <URL:http://www.merlyn.demo n.co.uk/> TP/BP/Delphi/JS/&c., FAQ topics, links.

      Comment

      • Albert Wagner

        #4
        Re: evaluation context of event handler string

        On Sun, 21 Sep 2003 21:34:11 +0100
        Dr John Stockton <spam@merlyn.de mon.co.uk> wrote:
        <snip>[color=blue]
        >
        > 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.[/color]
        <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

        Comment

        • Richard Cornford

          #5
          Re: evaluation context of event handler string

          "Albert Wagner" <alwagner@tcac. net> wrote in message
          news:2003092013 0555.6744455f.a lwagner@tcac.ne t...[color=blue]
          >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.[/color]

          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.protot ype.exampeFunc( ){
          var self = this;
          function innerFunction() {
          if(self.anyProp erty){
          self.anyMethod( );
          }
          }
          setTimeout(inne rFunction, 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.


          Comment

          • Csaba2000

            #6
            Re: evaluation context of event handler string

            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(func tion() {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(func tion () {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" <richard@litote s.demon.co.uk> wrote in message news:bkli0b$ips $1@hercules.bti nternet.com...[color=blue]
            > "Albert Wagner" <alwagner@tcac. net> wrote in message
            > news:2003092013 0555.6744455f.a lwagner@tcac.ne t...[color=green]
            > >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.[/color]
            >
            > 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.protot ype.exampeFunc( ){
            > var self = this;
            > function innerFunction() {
            > if(self.anyProp erty){
            > self.anyMethod( );
            > }
            > }
            > setTimeout(inne rFunction, 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.
            >
            >[/color]


            Comment

            • Lasse Reichstein Nielsen

              #7
              Re: evaluation context of event handler string

              "Csaba2000" <news@CsabaGabo r.com> writes:
              [color=blue]
              > for each myCell in the table we can do:
              >
              > myCell.onresize = function () {
              > var tmpVar = this;
              > setTimeout(func tion() {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.[/color]

              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!
              [color=blue]
              > I.e. what is that tmpVar bound to?[/color]

              For each call, it is bound to a new location, and the function inside
              is also new each time.
              [color=blue]
              > 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(func tion () {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.[/color]

              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.
              [color=blue]
              > 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)?[/color]

              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,ba r) {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 (){resizeHandle r2(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 - lrn@hotpop.com
              Art D'HTML: <URL:http://www.infimum.dk/HTML/randomArtSplit. html>
              'Faith without judgement merely degrades the spirit divine.'

              Comment

              • Csaba2000

                #8
                Re: evaluation context of event handler string

                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


                Comment

                • asdf asdf

                  #9
                  Re: evaluation context of event handler string

                  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!

                  Comment

                  • Lasse Reichstein Nielsen

                    #10
                    Re: evaluation context of event handler string

                    b0b0b0b@yahoo.c om (asdf asdf) writes:
                    [color=blue]
                    > Can you call what you did in your example a functor?[/color]

                    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 - lrn@hotpop.com
                    Art D'HTML: <URL:http://www.infimum.dk/HTML/randomArtSplit. html>
                    'Faith without judgement merely degrades the spirit divine.'

                    Comment

                    Working...