Broken object referencing from within an array?

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

    Broken object referencing from within an array?

    .... or my script, or my mind, or both?

    <html>
    <head>
    <title>Test</title>
    <meta http-equiv="Content-Type" content="text/html;
    charset=iso-8859-1">
    <script>
    function init() {
    var arr = document.getEle mentsByTagName( 'DIV');
    for (i=0; i<arr.length; i++) {
    arr[i].addEventListen er(
    'click',functio n(e){myFunction (arr[i],e);},true);
    }
    }

    function myFunction(obj, evt) {
    alert(obj.id);
    }
    </script>
    </head>

    <body bgcolor="#FFFFF F" onload="init()" >
    <div id='d1'>Some <a href="javascrip t:void(0)" id='s1'>link</a></div>
    <div id='d2'>Some <a href="javascrip t:void(0)" id='s2'>link</a></div>
    </body>
    </html>


    The above simply doesn't work - myFunction gets undefined as obj ! But
    with a bogus intermediary var it works like a charm:

    function init() {
    var arr = document.getEle mentsByTagName( 'DIV');
    var foo = null;
    for (i=0; i<arr.length; i++) {
    foo = arr[i];
    arr[i].addEventListen er(
    'click',functio n(e){myFunction (foo,e);},true) ;
    }
    }

    All the same in IE (with attachEvent). What a hey?

  • VK

    #2
    Re: Broken object referencing from within an array?

    The mistery is growing... I thought that maybe this way I was working
    with a collection object and not with a "blue blood" array, and it
    might cause some strange problem. So I did this profoundly idiotic
    algorithm just to be 100% sure I'm working with a real global array:

    <title>Untitl ed Document</title>
    <meta http-equiv="Content-Type" content="text/html;
    charset=iso-8859-1">
    <script>
    // Declaring a global array variable:
    var glbArray = new Array();

    function init() {
    var foo = null;
    var tmp = document.getEle mentsByTagName( 'DIV');
    for (i=0;i<tmp.leng th;i++) {
    // filling up the global array from the collection:
    glbArray.push(t mp[i]);
    }
    for (i=0; i<glbArray.leng th; i++) {
    //
    glbArray.addEve ntListener('cli ck',function(e) {myFunction(glb Array[i],e);},true);
    // ^ NOOP !!! myFunction gets undefined
    foo = glbArray[i];
    foo.addEventLis tener('click',f unction(e){myFu nction(foo,e);} ,true);
    // ^ Works like a charm !!!
    }
    }

    function myFunction(obj, evt) {
    alert(obj.id);
    }
    </script>
    </head>

    <body bgcolor="#FFFFF F" onload="init()" >
    <div id='d1'>Some <a href="javascrip t:void(0)" id='s1'>link</a></div>
    <div id='d2'>Some <a href="javascrip t:void(0)" id='s2'>link</a></div>
    </body>
    </html>

    All the same with IE. Any light?

    Comment

    • Michael Winter

      #3
      Re: Broken object referencing from within an array?

      On 30/05/2005 12:16, VK wrote:
      [color=blue]
      > ... or my script, or my mind, or both?[/color]

      Don't assume that a subject has been, or can be, read in full.
      [color=blue]
      > <script>[/color]

      The type attribute?
      [color=blue]
      > function init() {
      > var arr = document.getEle mentsByTagName( 'DIV');
      > for (i=0; i<arr.length; i++) {
      > arr[i].addEventListen er(
      > 'click',functio n(e){myFunction (arr[i],e);},true);
      > }
      > }[/color]

      When a closure is created, it doesn't take a snapshot of the variables
      in its scope chain - they remain live. By the time the listener is
      invoked, i will 'point' beyond the defined array contents, providing
      undefined to myFunction.

      With addEventListene r, or the on<type> properties, the better approach is:

      function init() {
      var arr = document.getEle mentsByTagName( 'div');

      for(var i = 0, n = arr.length; i < n; ++i) {

      /* Unless you have a reason to use
      * event capturing, don't bother.
      *
      * The capturing phase should only
      * be used to intercept events
      * before 'normal' event listeners
      * receive the event.
      */
      arr[i].addEventListen er('click', myFunction, false);
      }
      }
      function myFunction(e) {
      /* The this operator will refer
      * to the correct DIV element.
      */
      alert(this.id);
      }

      Unfortunately this won't work with Microsoft's attachEvent mechanism
      (the this operator isn't set correctly), which is why it's broken and I
      never use it.

      [snip]
      [color=blue]
      > But with a bogus intermediary var it works like a charm:[/color]

      No it doesn't.

      [snip]
      [color=blue]
      > for (i=0; i<arr.length; i++) {
      > foo = arr[i];[/color]

      The foo variable will always refer to the last DIV element encountered.
      Click the first link in your example and this is obvious.

      [snip]

      Mike

      --
      Michael Winter
      Replace ".invalid" with ".uk" to reply by e-mail.

      Comment

      • Richard Cornford

        #4
        Re: Broken object referencing from within an array?

        VK wrote:
        <snip>[color=blue]
        > function init() {
        > var arr = document.getEle mentsByTagName( 'DIV');
        > for (i=0; i<arr.length; i++) {
        > arr[i].addEventListen er(
        > 'click',functio n(e){myFunction (arr[i],e);},true);
        > }
        > }[/color]

        The function passed to abbEventListene r is executed long after the loop
        has finished executing, and when the containing function's local
        variable - i - has been incremented beyond the range of the contents of
        the - arr - collection.
        [color=blue]
        > The above simply doesn't work - myFunction gets undefined as obj ![/color]

        Yes, the contents of - arr[arr.length] - are undefined, and - i ==
        arr.length - at the end of the loop.
        [color=blue]
        > But
        > with a bogus intermediary var it works like a charm:[/color]

        You really should test these things a bit less superficially before
        making that type of statement. The local variable - foo - always
        contains a reference to the same DOM element regardless of how many
        event listeners were attached, and which is executed.
        [color=blue]
        > function init() {
        > var arr = document.getEle mentsByTagName( 'DIV');
        > var foo = null;
        > for (i=0; i<arr.length; i++) {
        > foo = arr[i];[/color]

        This assignment happens - arr.length - times, and the last assignment
        sets the value of - foo - that the event handlers will be using.
        [color=blue]
        > arr[i].addEventListen er(
        > 'click',functio n(e){myFunction (foo,e);},true) ;
        > }
        > }
        >
        > All the same in IE (with attachEvent). What a hey?[/color]

        Closures!

        <URL: http://jibbering.com/faq/faq_notes/closures.html >

        Richard.


        Comment

        • VK

          #5
          Re: Broken object referencing from within an array?

          > You really should test these things a bit less superficially[color=blue]
          > before making that type of statement.[/color]
          - Sorry, I really was in rush

          I solved the problem by moving the handler assignement out of the loop:
          <http://groups-beta.google.com/group/comp.lang.javas cript/browse_frm/thread/5f7aaccb9f46722 f/a5395b4a5dd6472 b#a5395b4a5dd64 72b>

          for (...) {
          assignHandler(a rr[i]);
          }

          and:

          function assignHandler(o bj) {
          obj.addEventLis tener('click', function(e){pro cessClick(obj, e);});
          }

          I guess it's one of these rather rare situations when the programming
          logic goes against the human one.
          However it was with closures (I guess there are reasons for them to be
          such), it's still "strange" that the program resolves obj at the
          function creation time, but refuses to do the same for arr[i] (an array
          element).

          Comment

          • Richard Cornford

            #6
            Re: Broken object referencing from within an array?

            VK wrote:
            <snip>[color=blue]
            > I guess it's one of these rather rare situations when
            > the programming logic goes against the human one.[/color]

            Speak for yourself. The scope structure in javascript is completely
            logical, mechanically and in the perception of (most) humans.
            [color=blue]
            > However it was with closures (I guess there are reasons
            > for them to be such), it's still "strange" that the program
            > resolves obj at the function creation time, but refuses to
            > do the same for arr[i] (an array element).[/color]

            Just once it would be nice if you would actually go and read the
            resources that people refer you to. You might then eventually get into a
            position where some of what you think is not twaddle.

            Richard.


            Comment

            • Lasse Reichstein Nielsen

              #7
              Re: Broken object referencing from within an array?

              "VK" <schools_ring@y ahoo.com> writes:
              [color=blue]
              > However it was with closures (I guess there are reasons for them to be
              > such), it's still "strange" that the program resolves obj at the
              > function creation time, but refuses to do the same for arr[i] (an array
              > element).[/color]

              Not so strange. There is only one "i" variable, and all the closures
              refer to that one. When it changes its value, it affects all closures.
              However, since "obj" is a formal parameter of a function, there is
              effectively a new variable for each call. It never varies, and each
              closure refers to its own version.

              /L
              --
              Lasse Reichstein Nielsen - lrn@hotpop.com
              DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleD OM.html>
              'Faith without judgement merely degrades the spirit divine.'

              Comment

              • Lasse Reichstein Nielsen

                #8
                Re: Broken object referencing from within an array?

                "Richard Cornford" <Richard@litote s.demon.co.uk> writes:
                [color=blue]
                > Speak for yourself. The scope structure in javascript is completely
                > logical, mechanically and in the perception of (most) humans.[/color]

                The scope structure is fine and logical, it's just its interaction
                with variables that won't feel natural to me. Probably because I
                learned closures in a functional language where variables didn't,
                well, *vary* very much. :)

                /L
                --
                Lasse Reichstein Nielsen - lrn@hotpop.com
                DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleD OM.html>
                'Faith without judgement merely degrades the spirit divine.'

                Comment

                Working...