'this', event handlers, and namespaces

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Jeff Bigham

    'this', event handlers, and namespaces

    Hi,

    Consider the following simplified code in which Foo is used as a
    'namespace':

    var Foo = {
    doAlert: function() {
    alert('hello');
    },
    myEventHandler: function(e) {
    this.doAlert();
    }
    }

    document.addEve ntListener('key down', Foo.doAlert, false);


    This gives me an error because when responding to the event, the
    object 'this' is the document because that's what I've attached the
    event handler to. I know I could just replace 'this' with "Foo.' but
    my understanding is that I take a performance hit every time I make
    such a global reference. And, since I'm developing a large web
    application in Javascript, I'd like to avoid unnecessary performance
    hits when possible.

    Anyone know what is the accepted standard of what to do in this case?

    Thanks!
    Jeff
  • RobG

    #2
    Re: 'this', event handlers, and namespaces

    On May 16, 9:27 am, Jeff Bigham <jeffrey.big... @gmail.comwrote :
    Hi,
    >
    Consider the following simplified code in which Foo is used as a
    'namespace':
    >
    var Foo = {
    doAlert: function() {
    alert('hello');
    },
    myEventHandler: function(e) {
    this.doAlert();
    }
    >
    }
    >
    document.addEve ntListener('key down', Foo.doAlert, false);
    >
    This gives me an error because when responding to the event, the
    object 'this' is the document because that's what I've attached the
    event handler to. I know I could just replace 'this' with "Foo.' but
    my understanding is that I take a performance hit every time I make
    such a global reference. And, since I'm developing a large web
    application in Javascript, I'd like to avoid unnecessary performance
    hits when possible.
    >
    Anyone know what is the accepted standard of what to do in this case?
    Try this thread:

    Subject: pseudo-namespacing in JavaScript
    <URL:
    http://groups.google.com.au/group/co...45e485506c4a92
    >

    --
    Rob

    Comment

    • jdd

      #3
      Re: 'this', event handlers, and namespaces

      On May 15, 7:27 pm, Jeff Bigham <jeffrey.big... @gmail.comwrote :
      Hi,
      >
      Consider the following simplified code in which Foo is used as a
      'namespace':
      >
      var Foo = {
        doAlert: function() {
          alert('hello');
        },
        myEventHandler: function(e) {
          this.doAlert();
        }
      >
      }
      >
      document.addEve ntListener('key down', Foo.doAlert, false);
      >
      This gives me an error because when responding to the event, the
      object 'this' is the document because that's what I've attached the
      event handler to.  I know I could just replace 'this' with "Foo.' but
      my understanding is that I take a performance hit every time I make
      such a global reference.  And, since I'm developing a large web
      application in Javascript, I'd like to avoid unnecessary performance
      hits when possible.
      >
      Anyone know what is the accepted standard of what to do in this case?
      >
      Thanks!
      Jeff
      I don't know if it's the accepted standard of what to do, but you
      could do something like:

      var Foo = {
        doAlert: function() {
          alert('hello');
        },
        myEventHandler: (function(t) {
      that = t;
      return function(e) {
          that.doAlert();
      };
      })(this)
      }

      I don't think this would be avoiding a performance hit though, and you
      probably shouldn't listen to my advice as I'm still a bit green on
      javascript. Additionally, I think the proper solution depends on what
      exactly you're trying to do.

      Comment

      • Thomas 'PointedEars' Lahn

        #4
        Re: 'this', event handlers, and namespaces

        Jeff Bigham wrote:
        Consider the following simplified code in which Foo is used as a
        'namespace':
        >
        var Foo = {
        doAlert: function() {
        alert('hello');
        },
        myEventHandler: function(e) {
        this.doAlert();
        }
        }
        >
        document.addEve ntListener('key down', Foo.doAlert, false);
        Probably you meant to write

        document.addEve ntListener('key down', Foo.myEventHand ler, false);

        instead, as there is no `this' in Foo.doAlert().
        This gives me an error because when responding to the event, the
        object 'this' is the document because that's what I've attached
        the event handler to.
        _added_ event _listener_ to

        This is a FAQ, and the solution is simple:

        document.addEve ntListener(
        'keydown',
        function(e) { Foo.myEventHand ler(e) },
        false);

        That said, by convention only names of properties that refer to
        constructors, and identifiers of constant primitive values, should begin
        with a capital letter.
        I know I could just replace 'this' with "Foo.' but my understanding
        is that I take a performance hit every time I make such a global reference.
        That is correct, as no identifier resolution is required for the `this'
        value of the execution context. However, the evaluation loop would be very
        short; the main issue here is maintainability : You really do not want to do
        search and replace when you have to rename `Foo' (and you should do that).
        And, since I'm developing a large web application in Javascript, I'd
        like to avoid unnecessary performance hits when possible.
        Good thinking, though.
        Anyone know what is the accepted standard of what to do in this case?
        There is no accepted standard about it, only common sense guided by the text
        of the ECMAScript Specification and by the reality of its implementations .


        PointedEars
        --
        realism: HTML 4.01 Strict
        evangelism: XHTML 1.0 Strict
        madness: XHTML 1.1 as application/xhtml+xml
        -- Bjoern Hoehrmann

        Comment

        • Thomas 'PointedEars' Lahn

          #5
          Re: 'this', event handlers, and namespaces

          jdd wrote:
          On May 15, 7:27 pm, Jeff Bigham <jeffrey.big... @gmail.comwrote :
          >Consider the following simplified code in which Foo is used as a
          >'namespace':
          >>
          >var Foo = {
          > doAlert: function() {
          > alert('hello');
          > },
          > myEventHandler: function(e) {
          > this.doAlert();
          > }
          >}
          >>
          >document.addEv entListener('ke ydown', Foo.doAlert, false);
          >>
          >This gives me an error because when responding to the event, the
          >object 'this' is the document because that's what I've attached the
          >event handler to. [...]
          >>
          >Anyone know what is the accepted standard of what to do in this case?
          >
          I don't know if it's the accepted standard of what to do, but you
          could do something like:
          >
          var Foo = {
          doAlert: function() {
          alert('hello');
          },
          myEventHandler: (function(t) {
          that = t;
          return function(e) {
          that.doAlert();
          };
          })(this)
          }
          This code does not address the problem at all. In the above scenario, the
          `myEventHandler ' property would be assigned a reference to a Function object
          that calls the doAlert() method of the *Global Object* (or the object
          referenced by the `that' property of an object in the scope chain, see
          below) instead of the object referred to by `Foo'. A TypeError exception on
          event is likely as the Global Object (or that object) is unlikely to have a
          method of that name. It is semantically equal to

          that = this;
          var Foo = {
          doAlert: function() {
          alert('hello');
          },
          myEventHandler: function(e) {
          that.doAlert();
          };
          };

          Also, the undeclared `that' identifier is inherently error-prone.

          Please trim your quotes as recommended e.g. in the FAQ Notes.


          PointedEars
          --
          Use any version of Microsoft Frontpage to create your site.
          (This won't prevent people from viewing your source, but no one
          will want to steal it.)
          -- from <http://www.vortex-webdesign.com/help/hidesource.htm>

          Comment

          • jdd

            #6
            Re: 'this', event handlers, and namespaces

            On May 15, 10:14 pm, Thomas 'PointedEars' Lahn <PointedE...@we b.de>
            wrote:
            This code does not address the problem at all. . .  
            You are correct, thanks for the explanation.

            Comment

            • Jorge

              #7
              Re: 'this', event handlers, and namespaces

              On May 16, 1:27 am, Jeff Bigham <jeffrey.big... @gmail.comwrote :
              Hi,
              >
              Consider the following simplified code in which Foo is used as a
              'namespace':
              >
              var Foo = {
                doAlert: function() {
                  alert('hello');
                },
                myEventHandler: function(e) {
                  this.doAlert();
                }
              >
              }
              >
              document.addEve ntListener('key down', Foo.doAlert, false);
              >
              This gives me an error because when responding to the event, the
              object 'this' is the document because that's what I've attached the
              event handler to.  I know I could just replace 'this' with "Foo.' but
              my understanding is that I take a performance hit every time I make
              such a global reference.  And, since I'm developing a large web
              application in Javascript, I'd like to avoid unnecessary performance
              hits when possible.
              >
              Anyone know what is the accepted standard of what to do in this case?
              >
              Thanks!
              Jeff
              <html lang="en"><head >
              <title>untitled </title></head><body>
              <script>
              var c= ": No closure";
              (function () {
              var d, e, c= ": anon f closure !";;
              var y= function (p) { return document.create Element(p) };
              var z= function (p) {
              document.body.a ppendChild(y('b r'));
              return document.body.a ppendChild(p);
              };
              var x= function (p) { (z(y('text'))). innerHTML= p };

              var foo= function (e) {
              var c= ": foo closure !";
              var me= arguments.calle e;
              me.doAlert= function() { x(this.src+': onClick'+c) };
              var doAlert= function() { x(this.src+': onMouseUp'+c) };

              //function object method : foo.doAlert()
              e.onclick= me.doAlert;
              //foo local var:
              e.onmouseup= doAlert;
              //anonymous function:
              e.onmouseover= function () { x(this.src+': onMouseOver'+c) };
              return e;
              };

              foo.too= function () { x(this.src+': onMouseOut'+c) };

              (e= foo(z(y('img')) )).src="http://tinyurl.com/6nhepj"
              //anonimous function object method 2:
              e.onmouseout= foo.too;
              (d=z(y('img'))) .src="http://tinyurl.com/5ehxv5"
              //anonimous function object method 2:
              d.onmouseout= foo.too;
              d.onmouseover= e.onmouseover;
              })();
              </script></body></html>

              Comment

              • Jorge

                #8
                Re: 'this', event handlers, and namespaces

                On May 16, 1:27 am, Jeff Bigham <jeffrey.big... @gmail.comwrote :
                Hi,
                >
                Consider the following simplified code in which Foo is used as a
                'namespace':
                >
                var Foo = {
                  doAlert: function() {
                    alert('hello');
                  },
                  myEventHandler: function(e) {
                    this.doAlert();
                  }
                >
                }
                >
                document.addEve ntListener('key down', Foo.doAlert, false);
                >
                This gives me an error because when responding to the event, the
                object 'this' is the document because that's what I've attached the
                event handler to.  I know I could just replace 'this' with "Foo.' but
                my understanding is that I take a performance hit every time I make
                such a global reference.  And, since I'm developing a large web
                application in Javascript, I'd like to avoid unnecessary performance
                hits when possible.
                >
                Anyone know what is the accepted standard of what to do in this case?
                >
                Thanks!
                Jeff
                <html lang="en"><head >
                <title>untitled </title></head><body>
                <script>
                var c= ": No closure";
                (function () {
                var d, e, c= ": anon f closure !";;
                var y= function (p) { return document.create Element(p) };
                var z= function (p) { return document.body.a ppendChild(p) };
                var x= function (p) {
                z(y('br'));
                (z(y('text'))). innerHTML= p;
                };

                var foo= function (e) {
                var c= ": foo closure !";
                var me= arguments.calle e;
                me.doAlert= function() { x(this.src+': onClick'+c) };
                var doAlert= function() { x(this.src+': onMouseUp'+c) };

                //function object method : foo.doAlert()
                e.onclick= me.doAlert;
                //foo local var:
                e.onmouseup= doAlert;
                //anonymous function:
                e.onmouseover= function () { x(this.src+': onMouseOver'+c) };
                return e;
                };

                foo.too= function () { x(this.src+': onMouseOut'+c) };

                (e= foo(z(y('img')) )).src="http://tinyurl.com/6nhepj"
                //anonimous function object method 2:
                e.onmouseout= foo.too;

                (d=z(y('img'))) .src="http://tinyurl.com/5ehxv5"
                //anonimous function object method 2:
                d.onmouseout= function () { x(this.src+': onMouseOut'+c) };
                d.onmouseover= function () { x(this.src+': onMouseOver'+c) };
                d.onclick= function() { x(this.src+': onClick'+c) };
                d.onmouseup= function () { x(this.src+': onMouseUp'+c) };

                (d=z(y('img'))) .src="http://tinyurl.com/5j84u6"
                //anonimous function object method 2:
                d.onmouseout= e.onmouseout;
                d.onmouseover= e.onmouseover;
                d.onclick= e.onclick;
                d.onmouseup= e.onmouseup;

                })();
                </script></body></html>

                Comment

                • Thomas 'PointedEars' Lahn

                  #9
                  Re: 'this', event handlers, and namespaces

                  Jorge wrote:
                  On May 16, 1:27 am, Jeff Bigham <jeffrey.big... @gmail.comwrote :
                  >Anyone know what is the accepted standard of what to do in this case?
                  >[...]
                  >
                  <html lang="en"><head >
                  <title>untitled </title></head><body>
                  <script>
                  var c= ": No closure";
                  (function () {
                  var d, e, c= ": anon f closure !";;
                  var y= function (p) { return document.create Element(p) };
                  var z= function (p) { return document.body.a ppendChild(p) };
                  var x= function (p) {
                  z(y('br'));
                  (z(y('text'))). innerHTML= p;
                  };
                  >
                  var foo= function (e) {
                  var c= ": foo closure !";
                  var me= arguments.calle e;
                  me.doAlert= function() { x(this.src+': onClick'+c) };
                  var doAlert= function() { x(this.src+': onMouseUp'+c) };
                  >
                  //function object method : foo.doAlert()
                  e.onclick= me.doAlert;
                  [...]
                  Sorry, this does not come even close to an approach that could make it to
                  standard procedure, much less to the standards-compliant approach that the
                  OP was following already. It is not even Valid markup to begin with:

                  W3C's easy-to-use markup validation service, based on SGML and XML parsers.



                  PointedEars
                  --
                  var bugRiddenCrashP ronePieceOfJunk = (
                  navigator.userA gent.indexOf('M SIE 5') != -1
                  && navigator.userA gent.indexOf('M ac') != -1
                  ) // Plone, register_functi on.js:16

                  Comment

                  • Jeff Bigham

                    #10
                    Re: 'this', event handlers, and namespaces

                    Anyone know what is the accepted standard of what to do in this case?
                    >
                    There is no accepted standard about it, only common sense guided by the text
                    of the ECMAScript Specification and by the reality of its implementations .
                    Thanks. What you suggested worked well.

                    -Jeff
                    PointedEars
                    --
                    realism: HTML 4.01 Strict
                    evangelism: XHTML 1.0 Strict
                    madness: XHTML 1.1 as application/xhtml+xml
                    -- Bjoern Hoehrmann

                    Comment

                    • Bjoern Hoehrmann

                      #11
                      Re: 'this', event handlers, and namespaces

                      * Jeff Bigham wrote in comp.lang.javas cript:
                      >Consider the following simplified code in which Foo is used as a
                      >'namespace':
                      >
                      >var Foo = {
                      doAlert: function() {
                      alert('hello');
                      },
                      myEventHandler: function(e) {
                      this.doAlert();
                      }
                      >}
                      >
                      >document.addEv entListener('ke ydown', Foo.doAlert, false);
                      You would have to call the event handler method 'handleEvent' and pass
                      the object rather than the function to addEventListene r, i.e., like so:

                      var Foo = {
                      doAlert: function() {
                      alert('hello');
                      },
                      handleEvent: function(e) {
                      this.doAlert();
                      }
                      }

                      document.addEve ntListener('key down', Foo, false);

                      With your approach `this` should always be bound to e.currentTarget .
                      --
                      Björn Höhrmann · mailto:bjoern@h oehrmann.de · http://bjoern.hoehrmann.de
                      Weinh. Str. 22 · Telefon: +49(0)621/4309674 · http://www.bjoernsworld.de
                      68309 Mannheim · PGP Pub. KeyID: 0xA4357E78 · http://www.websitedev.de/

                      Comment

                      Working...