Attach a class method to event handler

Discussion in 'Javascript' started by Ugo, May 29, 2008.

  1. Ugo

    Ugo Guest

    Hi guys,

    until now I make so:

    HTML:
    <div id="my_div"><!-- content --></div>
    
    [simple-js]
    MyClass.prototype.doSomething = function( ) {};
    MyClass.prototype.assignFun = function( )
    {
    var selfObj = this;
    document.getElementById('my_div').onclick = function ( e )
    {
    selfObj.doSomethingWith( e || event );
    }
    }
    
    How do I avoid the closure of my object reference?
    And MyClass is not a Singleton...
    Ugo, May 29, 2008
    #1
    1. Advertising

  2. On May 29, 8:36 am, Ugo <> wrote:
    > Hi guys,
    >
    > until now I make so:
    >
    >
    HTML:
    > <div id="my_div"><!-- content --></div>
    >
    > [simple-js]
    > MyClass.prototype.doSomething = function( ) {};
    > MyClass.prototype.assignFun = function( )
    > {
    >    var selfObj = this;
    >    document.getElementById('my_div').onclick = function ( e )
    >    {
    >       selfObj.doSomethingWith( e || event );
    >    }
    >
    > }
    >
    > How do I avoid the closure of my object reference?
    > And MyClass is not a Singleton...[/color]
    
    if you want to avoid the closure then don't create one with selfObj.
    
    MyClass.prototype.doSomething = function( ) {};
    MyClass.prototype.assignFun = function( )
    {
    document.getElementById('my_div').onclick = function ( e )
    {
    MyClass.prototype.doSomethingWith( e || event );
    }
    
    }
    
    or perhaps even
    
    MyClass.prototype.doSomething = function( ) {};
    MyClass.prototype.assignFun = function( )
    {
    document.getElementById('my_div').onclick =
    MyClass.prototype.doSomethingWith;
    }
    
    
    It may be a mistake to be thinking in terms of "MyClass" as JavaScript
    doesn't have classes.
    
    Peter
    Peter Michaux, May 29, 2008
    #2
    1. Advertising

  3. Peter Michaux wrote:
    > On May 29, 8:36 am, Ugo <> wrote:
    >> until now I make so:
    >>
    >>
    HTML:
    >> <div id="my_div"><!-- content --></div>
    >>
    >> [simple-js]
    >> MyClass.prototype.doSomething = function( ) {};
    >> MyClass.prototype.assignFun = function( )
    >> {
    >>    var selfObj = this;
    >>    document.getElementById('my_div').onclick = function ( e )
    >>    {
    >>       selfObj.doSomethingWith( e || event );
    >>    }
    >> }
    >>
    >> How do I avoid the closure of my object reference?[/color][/color]
    
    MyClass.prototype.assignFun = function() {
    document.getElementById('my_div').onclick = (function(o) {
    return function(e) {
    o.doSomethingWith(e || window.event);
    };
    })(this);
    };
    
    That said, you should avoid mixing "DOM Level 0" and DOM Level 2 features in
    one statement; at least you should feature-test both before you mix them.
    Such Reference Worms[tm] are error-prone anyway.  Consider this (still
    error-prone because of the partially proprietary, apparently untestable
    approach):
    
    MyClass.prototype.assignFun = function() {
    if (isMethod(document, "getElementById"))
    {
    var target = document.getElementById('my_div');
    if (target)
    {
    target.onclick = (function(o) {
    return function(e) {
    o.doSomethingWith(e || window.event);
    };
    })(this);
    }
    }
    };
    [color=blue][color=green]
    >> And MyClass is not a Singleton...[/color]
    >
    > if you want to avoid the closure then don't create one with selfObj.
    >
    > MyClass.prototype.doSomething = function( ) {};
    > MyClass.prototype.assignFun = function( )
    > {
    >    document.getElementById('my_div').onclick = function ( e )
    >    {
    >       MyClass.prototype.doSomethingWith( e || event );
    >    }
    > }[/color]
    
    While this is not the least equivalent to the original, `MyClass' is the
    bound "variable" of the closure then.
    [color=blue]
    > or perhaps even
    >
    > MyClass.prototype.doSomething = function( ) {};
    > MyClass.prototype.assignFun = function( )
    > {
    >    document.getElementById('my_div').onclick =
    >      MyClass.prototype.doSomethingWith;
    > }[/color]
    
    It is getting worse.  Now the method of the prototype object will be called
    as a method of the Global Object.
    [color=blue]
    > It may be a mistake to be thinking in terms of "MyClass" as JavaScript
    > doesn't have classes.[/color]
    
    That, at least, is correct.
    
    
    PointedEars
    --
    var bugRiddenCrashPronePieceOfJunk = (
    navigator.userAgent.indexOf('MSIE 5') != -1
    && navigator.userAgent.indexOf('Mac') != -1
    )  // Plone, register_function.js:16
    Thomas 'PointedEars' Lahn, May 30, 2008
    #3
  4. Ugo

    RobG Guest

    On May 30, 10:35 am, Thomas 'PointedEars' Lahn <>
    wrote:
    [...]
    > That said, you should avoid mixing "DOM Level 0" and DOM Level 2 features in
    > one statement; at least you should feature-test both before you mix them.
    > Such Reference Worms[tm] are error-prone anyway. Consider this (still
    > error-prone because of the partially proprietary, apparently untestable
    > approach):
    >
    > MyClass.prototype.assignFun = function() {
    > if (isMethod(document, "getElementById"))
    > {
    > var target = document.getElementById('my_div');
    > if (target)
    > {
    > target.onclick = (function(o) {
    > return function(e) {
    > o.doSomethingWith(e || window.event);
    > };
    > })(this);
    > }


    Doesn't that create a circular reference to the DOM element referenced
    by target? Should that be avoided by using, at this point:

    target = null;


    > }
    > };



    --
    Rob
    RobG, May 30, 2008
    #4
  5. On May 29, 5:35 pm, Thomas 'PointedEars' Lahn <>
    wrote:
    > Peter Michaux wrote:
    > > On May 29, 8:36 am, Ugo <> wrote:
    > >> until now I make so:

    >
    > >>
    HTML:
    > >> <div id="my_div"><!-- content --></div>[/color][/color]
    >[color=green][color=darkred]
    > >> [simple-js]
    > >> MyClass.prototype.doSomething = function( ) {};
    > >> MyClass.prototype.assignFun = function( )
    > >> {
    > >>    var selfObj = this;
    > >>    document.getElementById('my_div').onclick = function ( e )
    > >>    {
    > >>       selfObj.doSomethingWith( e || event );
    > >>    }
    > >> }[/color][/color]
    >[color=green][color=darkred]
    > >> How do I avoid the closure of my object reference?[/color][/color]
    >
    >   MyClass.prototype.assignFun = function() {
    >     document.getElementById('my_div').onclick = (function(o) {
    >       return function(e) {
    >         o.doSomethingWith(e || window.event);
    >       };
    >     })(this);
    >   };
    >
    > That said, you should avoid mixing "DOM Level 0" and DOM Level 2 features in
    > one statement; at least you should feature-test both before you mix them.
    > Such Reference Worms[tm] are error-prone anyway.  Consider this (still
    > error-prone because of the partially proprietary, apparently untestable
    > approach):
    >
    >   MyClass.prototype.assignFun = function() {
    >     if (isMethod(document, "getElementById"))
    >     {
    >       var target = document.getElementById('my_div');
    >       if (target)
    >       {
    >         target.onclick = (function(o) {
    >           return function(e) {
    >             o.doSomethingWith(e || window.event);
    >           };
    >         })(this);
    >       }
    >     }
    >   };
    >[color=green][color=darkred]
    > >> And MyClass is not a Singleton...[/color][/color]
    >[color=green]
    > > if you want to avoid the closure then don't create one with selfObj.[/color]
    >[color=green]
    > > MyClass.prototype.doSomething = function( ) {};
    > > MyClass.prototype.assignFun = function( )
    > > {
    > >    document.getElementById('my_div').onclick = function ( e )
    > >    {
    > >       MyClass.prototype.doSomethingWith( e || event );
    > >    }
    > > }[/color]
    >
    > While this is not the least equivalent to the original, `MyClass' is the
    > bound "variable" of the closure then.
    >[color=green]
    > > or perhaps even[/color]
    >[color=green]
    > > MyClass.prototype.doSomething = function( ) {};
    > > MyClass.prototype.assignFun = function( )
    > > {
    > >    document.getElementById('my_div').onclick =
    > >      MyClass.prototype.doSomethingWith;
    > > }[/color]
    >
    > It is getting worse.  Now the method of the prototype object will be called
    > as a method of the Global Object.[/color]
    
    It wasn't clear what the code in the original post was doing or even
    if the doSomething function uses "this". Without a complete question a
    complete answer is not possible.
    
    [snip]
    
    Peter
    Peter Michaux, May 30, 2008
    #5
  6. Peter Michaux wrote:
    > On May 29, 5:35 pm, Thomas 'PointedEars' Lahn <>
    > wrote:
    >> Peter Michaux wrote:
    >>> [...]
    >>> MyClass.prototype.doSomething = function( ) {};
    >>> MyClass.prototype.assignFun = function( )
    >>> {
    >>> document.getElementById('my_div').onclick = function ( e )
    >>> {
    >>> MyClass.prototype.doSomethingWith( e || event );
    >>> }
    >>> }

    >>
    >> While this is not the least equivalent to the original, `MyClass' is the
    >> bound "variable" of the closure then.
    >>
    >>> or perhaps even
    >>>
    >>> MyClass.prototype.doSomething = function( ) {};
    >>> MyClass.prototype.assignFun = function( )
    >>> {
    >>> document.getElementById('my_div').onclick =
    >>> MyClass.prototype.doSomethingWith;
    >>> }

    >> It is getting worse. Now the method of the prototype object will be called
    >> as a method of the Global Object.

    >
    > It wasn't clear what the code in the original post was doing or even
    > if the doSomething function uses "this". Without a complete question a
    > complete answer is not possible.


    You are winding around the issue.

    It does not matter whether the purpose of the code was clear (to you) or
    not; using the `this' reference in a prototype method and using the
    reference to the prototype object there are clearly not the same thing, nor
    are assigning the reference to a prototype method versus assigning a
    reference to a Function object that calls this prototype method (as
    inherited through the prototype chain). So it cannot be expected to have
    the same outcome, and is therefore not the least equivalent to one another.

    Host objects aside, consider this (in Fx 2.0.0.14):

    function MyObject(answer) {
    this.bar = function() {
    window.alert(answer);
    };
    }

    MyObject.prototype.foo = function() {
    // 42
    this.bar();

    // 23,function MyObject...
    MyObject.prototype.bar();

    var f = MyObject.prototype.bar;

    // 23,[Window]
    f();
    };

    MyObject.prototype.bar = function() {
    window.alert([23, this.constructor]);
    }

    (new MyObject(42)).foo();

    Trimming quotes a bit more would increase the chance of your postings being
    recognized in the future.


    PointedEars
    --
    var bugRiddenCrashPronePieceOfJunk = (
    navigator.userAgent.indexOf('MSIE 5') != -1
    && navigator.userAgent.indexOf('Mac') != -1
    ) // Plone, register_function.js:16
    Thomas 'PointedEars' Lahn, May 30, 2008
    #6
  7. Thomas 'PointedEars' Lahn a écrit :
    > Trimming quotes a bit more would increase the chance of your postings being
    > recognized in the future.


    FFS, who do you think you are ? Go to hell !

    --
    laurent
    Laurent vilday, May 30, 2008
    #7
  8. Ugo

    Ugo Guest

    >>> [simple-js]
    >>> MyClass.prototype.doSomething = function( ) {};
    >>> MyClass.prototype.assignFun = function( )
    >>> {
    >>> var selfObj = this;
    >>> document.getElementById('my_div').onclick = function ( e )
    >>> {
    >>> selfObj.doSomethingWith( e || event );
    >>> }
    >>> }
    >>>
    >>> How do I avoid the closure of my object reference?

    >
    > MyClass.prototype.assignFun = function() {
    > document.getElementById('my_div').onclick = (function(o) {
    > return function(e) {
    > o.doSomethingWith(e || window.event);
    > };
    > })(this);
    > };
    >
    > That said, you should avoid mixing "DOM Level 0" and DOM Level 2 features in
    > one statement;


    i.e.?
    Where did I mix?
    So, if I am not mistaken, you make a closure too:
    your approach is more elegant, but you close the parameter "o" of the
    anonymous function, or not?

    > at least you should feature-test both before you mix them.


    it was only example...
    Ugo, May 30, 2008
    #8
  9. On May 30, 4:43 am, Thomas 'PointedEars' Lahn <>
    wrote:
    > Peter Michaux wrote:
    > > On May 29, 5:35 pm, Thomas 'PointedEars' Lahn <>
    > > wrote:
    > >> Peter Michaux wrote:
    > >>> [...]
    > >>> MyClass.prototype.doSomething = function( ) {};
    > >>> MyClass.prototype.assignFun = function( )
    > >>> {
    > >>> document.getElementById('my_div').onclick = function ( e )
    > >>> {
    > >>> MyClass.prototype.doSomethingWith( e || event );
    > >>> }
    > >>> }

    >
    > >> While this is not the least equivalent to the original, `MyClass' is the
    > >> bound "variable" of the closure then.

    >
    > >>> or perhaps even

    >
    > >>> MyClass.prototype.doSomething = function( ) {};
    > >>> MyClass.prototype.assignFun = function( )
    > >>> {
    > >>> document.getElementById('my_div').onclick =
    > >>> MyClass.prototype.doSomethingWith;
    > >>> }
    > >> It is getting worse. Now the method of the prototype object will be called
    > >> as a method of the Global Object.

    >
    > > It wasn't clear what the code in the original post was doing or even
    > > if the doSomething function uses "this". Without a complete question a
    > > complete answer is not possible.

    >
    > You are winding around the issue.


    No I'm not.

    > It does not matter whether the purpose of the code was clear (to you) or
    > not;


    If the question is not clear then many answers are possible.

    > using the `this' reference in a prototype method


    There was no use of "this" in the original question.

    > and using the
    > reference to the prototype object there are clearly not the same thing, nor
    > are assigning the reference to a prototype method versus assigning a
    > reference to a Function object that calls this prototype method (as
    > inherited through the prototype chain). So it cannot be expected to have
    > the same outcome, and is therefore not the least equivalent to one another.


    But it may have acceptable outcome. The question was not clear. That
    was actually one point I was making with my original answer.

    [snip]


    Peter
    Peter Michaux, May 30, 2008
    #9
  10. Peter Michaux wrote:
    > On May 30, 4:43 am, Thomas 'PointedEars' Lahn <>
    > wrote:
    >> Peter Michaux wrote:
    >>> On May 29, 5:35 pm, Thomas 'PointedEars' Lahn <>
    >>> wrote:
    >>>> Peter Michaux wrote:
    >>>>> [...]
    >>>>> MyClass.prototype.doSomething = function( ) {};
    >>>>> MyClass.prototype.assignFun = function( )
    >>>>> {
    >>>>> document.getElementById('my_div').onclick = function ( e )
    >>>>> {
    >>>>> MyClass.prototype.doSomethingWith( e || event );
    >>>>> }
    >>>>> }
    >>>>
    >>>> While this is not the least equivalent to the original, `MyClass' is the
    >>>> bound "variable" of the closure then.
    >>> [...]
    >>> It wasn't clear what the code in the original post was doing or even
    >>> if the doSomething function uses "this". Without a complete question a
    >>> complete answer is not possible.

    >> You are winding around the issue.

    >
    > No I'm not.


    You are overlooking something important, then.

    >> It does not matter whether the purpose of the code was clear (to you) or
    >> not;

    >
    > If the question is not clear then many answers are possible.


    True. However, a good answer would at least provide an equivalent solution
    to the presented problem (which was, without doubt, how to avoid closures).
    Yours did not provide an equivalent solution. (Mine did provide a
    equivalent solution, but maybe no solution to the OP's problem. Insofar
    both of us might have failed to provide a good answer.)

    >> using the `this' reference in a prototype method

    >
    > There was no use of "this" in the original question.


    My example shows that this does not matter. Literally.

    I have trimmed the quote more so that you may see the point more easily.


    PointedEars
    --
    Anyone who slaps a 'this page is best viewed with Browser X' label on
    a Web page appears to be yearning for the bad old days, before the Web,
    when you had very little chance of reading a document written on another
    computer, another word processor, or another network. -- Tim Berners-Lee
    Thomas 'PointedEars' Lahn, May 30, 2008
    #10
  11. On May 30, 12:33 pm, Thomas 'PointedEars' Lahn <>
    wrote:
    > Peter Michaux wrote:
    > > On May 30, 4:43 am, Thomas 'PointedEars' Lahn <>
    > > wrote:
    > >> Peter Michaux wrote:
    > >>> On May 29, 5:35 pm, Thomas 'PointedEars' Lahn <>
    > >>> wrote:
    > >>>> Peter Michaux wrote:
    > >>>>> [...]
    > >>>>> MyClass.prototype.doSomething = function( ) {};
    > >>>>> MyClass.prototype.assignFun = function( )
    > >>>>> {
    > >>>>> document.getElementById('my_div').onclick = function ( e )
    > >>>>> {
    > >>>>> MyClass.prototype.doSomethingWith( e || event );
    > >>>>> }
    > >>>>> }

    >
    > >>>> While this is not the least equivalent to the original, `MyClass' is the
    > >>>> bound "variable" of the closure then.
    > >>> [...]
    > >>> It wasn't clear what the code in the original post was doing or even
    > >>> if the doSomething function uses "this". Without a complete question a
    > >>> complete answer is not possible.
    > >> You are winding around the issue.

    >
    > > No I'm not.

    >
    > You are overlooking something important, then.
    >
    > >> It does not matter whether the purpose of the code was clear (to you) or
    > >> not;

    >
    > > If the question is not clear then many answers are possible.

    >
    > True. However, a good answer would at least provide an equivalent solution
    > to the presented problem (which was, without doubt, how to avoid closures).
    > Yours did not provide an equivalent solution. (Mine did provide a
    > equivalent solution, but maybe no solution to the OP's problem. Insofar
    > both of us might have failed to provide a good answer.)
    >
    > >> using the `this' reference in a prototype method

    >
    > > There was no use of "this" in the original question.

    >
    > My example shows that this does not matter. Literally.
    >
    > I have trimmed the quote more so that you may see the point more easily.


    I can see that you have done a very nice job at trimming the quotes.

    Peter

    [snip] <-- see how I trimmed your signature.
    Peter Michaux, May 30, 2008
    #11
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Nikhil Patel
    Replies:
    3
    Views:
    2,833
    Ken Cox [Microsoft MVP]
    Oct 7, 2004
  2. =?Utf-8?B?TmlybWFsa3VtYXI=?=

    How to attach an event to dynamically created control in VB.NET

    =?Utf-8?B?TmlybWFsa3VtYXI=?=, Jan 12, 2005, in forum: ASP .Net
    Replies:
    1
    Views:
    7,585
    Philip Q [MVP]
    Jan 12, 2005
  3. Replies:
    1
    Views:
    686
    Damien
    Feb 22, 2007
  4. Replies:
    0
    Views:
    640
  5. Warren Tang
    Replies:
    1
    Views:
    535
    Warren Tang
    Sep 17, 2008
Loading...

Share This Page