Closures Explained

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Lasse Reichstein Nielsen

    #31
    Re: Closures Explained

    sasuke <database666@gm ail.comwrites:
    On Oct 10, 9:07 pm, Lasse Reichstein Nielsen <lrn.unr...@gma il.com>
    wrote:
    >>
    >[snip]
    >>
    >A closure is a piece of code together with a binding of values to the
    >free variables of that code.
    >>
    >A free variable is one that occur in the code, but is not declared
    >there.
    >
    So does it mean that even global variables in Javascript are `free
    variables' given the fact that they can be used without being declared
    or is it that the definition is a loose one?
    I variable is not inherently free or not. A variable occurence in a
    part of a program, e.g., function declaration, is free in that
    function if the function doesn't contain a declaration of that variable.

    Example:

    function foo(x) {
    return function(y) {
    alert(x+y);
    }
    }

    This entire function has only one free variable: "alert".
    The variable occurences "x" and "y" are bound by the argument
    declarations of the surrounding functions.

    The inner function:
    function(y) { alert(x+y); }
    has two free variables: "alert" and "x".

    Notice that the same occurence of "x" can be both free and bound
    depending on the scope one consider.

    Also, given the function:
    >
    ---------------------------------->B--------------------------
    function attachEvents() {
    var divs = document.getEle mentsByTagName( "DIV");
    if(!divs) return;
    for(var i = 0, maxI = divs.length; i < maxI; ++i) {
    var d = divs[i];
    d.onclick = function() {
    // some complicated processing with a lot of variables
    alert("Hello from " + d.id);
    }
    }
    }
    window.onload = function() {
    attachEvents();
    // something complicated
    attachEvents();
    }
    ---------------------------------->B--------------------------
    >
    Will the second invocation of the function `attachEvents' make the
    execution context of the first run along with the previously created
    function objects eligible for garbage collection or do they need to be
    explicitly grounded [set to null]?
    That depends entirely on the javascript implementation.

    Best case, nothing remains and the garbage collector claims it all.

    Worst case, the garbage collector barfs on the DOM->JS function->DOM
    dependencies and collects nothing. That's a memory leak. I believe
    IE 6 might do just that.

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

    Comment

    • David Mark

      #32
      Re: Closures Explained

      On Oct 13, 1:14 pm, sasuke <database...@gm ail.comwrote:
      On Oct 10, 9:07 pm, Lasse Reichstein Nielsen <lrn.unr...@gma il.com>
      wrote:
      >
      >
      >
      [snip]
      >
      A closure is a piece of code together with a binding of values to the
      free variables of that code.
      >
      A free variable is one that occur in the code, but is not declared
      there.
      >
      So does it mean that even global variables in Javascript are `free
      variables' given the fact that they can be used without being declared
      or is it that the definition is a loose one?
      The term "free variable" (as defined here) could be used to describe
      global variables that are referenced within functions. Regardless,
      global variables are not part of the binding described in the closure
      definition.
      >
      Also, given the function:
      >
      ---------------------------------->B--------------------------
      function attachEvents() {
        var divs = document.getEle mentsByTagName( "DIV");
      Inefficient. Use the collection itself.
        if(!divs) return;
      You don't need to do that with gEBTN.
        for(var i = 0, maxI = divs.length; i < maxI; ++i) {
      Inefficient. Use a while that counts down to 0.
          var d = divs[i];
          d.onclick = function() {
            // some complicated processing with a lot of variables
            alert("Hello from " + d.id);
          }
        }}
      You are leaking memory. Every one of these creates this chain:

      [DOM element X] ---onclick---[anon function] ---[variable object]
      ---[DOM element A]

      You forgot to set divs to null too. Same issue.

      Unfortunately, your design doesn't allow you to set d to null.

      function attachEvents() {
      var el, index = document.getEle mentsByTagName( 'div').length;
      while (index--) {
      el = document.getEle mentsByTagName( 'div')[index];
      el.onclick = (function(id) {
      return function() { alert('Hello from ' + id); };
      })(el.id);
      }
      el = null;
      }

      Or better yet, attach one listener and use delegation.

      Comment

      • David Mark

        #33
        Re: Closures Explained

        On Oct 13, 2:56 pm, David Mark <dmark.cins...@ gmail.comwrote:
        On Oct 13, 1:14 pm, sasuke <database...@gm ail.comwrote:
        >
        [snip]
        ---[DOM element A]
        Typo. Should be X of course (not A.) The whole point is that it is a
        circular reference.

        Comment

        • Jorge

          #34
          Re: Closures Explained

          On Oct 13, 8:56 pm, David Mark <dmark.cins...@ gmail.comwrote:
          >
          function attachEvents() {
            var el, index = document.getEle mentsByTagName( 'div').length;
            while (index--) {
               el = document.getEle mentsByTagName( 'div')[index];
               el.onclick = (function(id) {
                  return function() { alert('Hello from ' + id); };
               })(el.id);
            }
            el = null;
          >
          }

          function attachEvents () {
          var divs= document.getEle mentsByTagName( 'div'),
          f= function (event) { alert(this.id) },
          index= divs.length;

          while (index--) { divs[index].onclick= f }
          }

          --
          Jorge.

          Comment

          • David Mark

            #35
            Re: Closures Explained

            On Oct 14, 10:00 am, Jorge <jo...@jorgecha morro.comwrote:
            On Oct 13, 8:56 pm, David Mark <dmark.cins...@ gmail.comwrote:
            >
            >
            >
            function attachEvents() {
              var el, index = document.getEle mentsByTagName( 'div').length;
              while (index--) {
                 el = document.getEle mentsByTagName( 'div')[index];
                 el.onclick = (function(id) {
                    return function() { alert('Hello from ' + id); };
                 })(el.id);
              }
              el = null;
            >
            }
            >
            function attachEvents () {
              var divs= document.getEle mentsByTagName( 'div'),
              f= function (event) { alert(this.id) },
              index= divs.length;
            >
              while (index--) { divs[index].onclick= f }
            >
            }
            >
            It is pointless to rewrite this pattern (diminishing returns.) A
            single listener should be used.

            Comment

            • David Mark

              #36
              Re: Closures Explained

              On Oct 14, 10:00 am, Jorge <jo...@jorgecha morro.comwrote:
              On Oct 13, 8:56 pm, David Mark <dmark.cins...@ gmail.comwrote:
              >
              >
              >
              function attachEvents() {
                var el, index = document.getEle mentsByTagName( 'div').length;
                while (index--) {
                   el = document.getEle mentsByTagName( 'div')[index];
                   el.onclick = (function(id) {
                      return function() { alert('Hello from ' + id); };
                   })(el.id);
                }
                el = null;
              >
              }
              >
              function attachEvents () {
                var divs= document.getEle mentsByTagName( 'div'),
                f= function (event) { alert(this.id) },
                index= divs.length;
              >
                while (index--) { divs[index].onclick= f }
              >
              }
              Oops, forgot to mention that this will leak memory in IE.

              [divs]->[DOM node]->[f]->[variable object]->[divs]

              Add divs = null to break the chain at the end (of course.)

              See the link posted previously.


              Comment

              • Lasse Reichstein Nielsen

                #37
                Re: Closures Explained

                David Mark <dmark.cinsoft@ gmail.comwrites :
                On Oct 14, 7:16 am, Conrad Lender <crlen...@yahoo .comwrote:
                >[second attempt; the first didn't show up for some reason]
                >>
                >On 2008-10-13 20:56, David Mark wrote:
                function attachEvents() {
                  var el, index = document.getEle mentsByTagName( 'div').length;
                  while (index--) {
                     el = document.getEle mentsByTagName( 'div')[index];
                >>
                >Are you suggesting that calling getElementsByTa gName() in a loop is more
                >efficient than storing a reference to the collection in a variable, and
                >
                Yes. Browsers optimize for that pattern.
                Do you have any references for that? It sounds likely that they do
                something smart, but I find it unlikely that it will be faster
                to call a function to return the same value again than just looking
                it up in a local variable.
                Nonsense. Opera has a long article on their site about this.
                Link?

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

                Comment

                • David Mark

                  #38
                  Re: Closures Explained

                  On Oct 14, 6:32 pm, Lasse Reichstein Nielsen <lrn.unr...@gma il.com>
                  wrote:
                  David Mark <dmark.cins...@ gmail.comwrites :
                  On Oct 14, 7:16 am, Conrad Lender <crlen...@yahoo .comwrote:
                  [second attempt; the first didn't show up for some reason]
                  >
                  On 2008-10-13 20:56, David Mark wrote:
                  function attachEvents() {
                    var el, index = document.getEle mentsByTagName( 'div').length;
                    while (index--) {
                       el = document.getEle mentsByTagName( 'div')[index];
                  >
                  Are you suggesting that calling getElementsByTa gName() in a loop is more
                  efficient than storing a reference to the collection in a variable, and
                  >
                  Yes.  Browsers optimize for that pattern.
                  >
                  Do you have any references for that? It sounds likely that they do
                  I have been trying to dig it up myself.
                  something smart, but I find it unlikely that it will be faster
                  Thanks for that, but it is possible that I did something dumb in this
                  case. The fact that I can't find the article is not encouraging.
                  to call a function to return the same value again than just looking
                  it up in a local variable.
                  Well, define looking it up in a local variable when the local variable
                  is a reference to a live nodelist? I can't as I don't write browsers.
                  >
                  Nonsense.  Opera has a long article on their site about this.
                  >
                  Link?
                  Not on Opera from what I can see.

                  Comment

                  • Conrad Lender

                    #39
                    Re: Closures Explained

                    On 2008-10-14 23:42, David Mark wrote:
                    function attachEvents() {
                    var el, index = document.getEle mentsByTagName( 'div').length;
                    while (index--) {
                    el = document.getEle mentsByTagName( 'div')[index];
                    >>
                    >Are you suggesting that calling getElementsByTa gName() in a loop is more
                    >efficient than storing a reference to the collection in a variable, and
                    >
                    Yes. Browsers optimize for that pattern.
                    I would also like to see a source for that.
                    >using the variable in the loop? I doubt that, and some preliminary
                    >
                    Doubt it all you want.
                    >
                    >testing shows that your recommendation is consistently slower than
                    >sasuke's; in some implementations (Opera, Safari) even by a factor of 4.
                    >
                    Nonsense. Opera has a long article on their site about this.
                    Well. Here I am, having tested this in 5 current browsers (not
                    comprehensive, yes, but as I said, they were preliminary tests), and
                    here you are saying "nonsense". Is that all you've got?


                    - Conrad

                    Comment

                    • David Mark

                      #40
                      Re: Closures Explained

                      On Oct 14, 6:54 pm, Conrad Lender <crlen...@yahoo .comwrote:
                      On 2008-10-14 23:42, David Mark wrote:
                      >
                      function attachEvents() {
                        var el, index = document.getEle mentsByTagName( 'div').length;
                        while (index--) {
                           el = document.getEle mentsByTagName( 'div')[index];
                      >
                      Are you suggesting that calling getElementsByTa gName() in a loop is more
                      efficient than storing a reference to the collection in a variable, and
                      >
                      Yes.  Browsers optimize for that pattern.
                      >
                      I would also like to see a source for that.
                      >
                      using the variable in the loop? I doubt that, and some preliminary
                      >
                      Doubt it all you want.
                      >
                      testing shows that your recommendation is consistently slower than
                      sasuke's; in some implementations (Opera, Safari) even by a factor of 4.
                      >
                      Nonsense.  Opera has a long article on their site about this.
                      >
                      Well. Here I am, having tested this in 5 current browsers (not
                      Yes, there you are. Your testing has been previously proven suspect.
                      Pardon me if I am non-responsive.

                      Comment

                      • RobG

                        #41
                        Re: Closures Explained

                        On Oct 11, 1:38 am, MartinRineh...@ gmail.com wrote:
                        I've rewritten a short article explaining closures in JavaScript.
                        It's
                        at:
                        >

                        >
                        A big Thank You to PointedEars and Jorge for helping me get closer to
                        the truth.
                        Seems the article hasn't been updated since you started this thread,
                        are you going to?

                        Don't be discouraged by criticism, teaching something is a very good
                        way to learn it thoroughly if you are prepared to learn yourself from
                        the experience.

                        A couple of tips, some mentioned by others, some not:

                        1. Closures are a feature of ECMAScript. Javascript is not a subset
                        of ECMAScript, quite the opposite, so I'd remove the note below the
                        title. Crockford’s book is just his opinion on some features of the
                        language that he considers good/bad/ugly, I don’t think it’s a serious
                        attempt to modify the standard (although I haven’t read it).

                        2. The article’s definition of a closure is meaningless to me, but
                        then again, I haven’t read a one-line description that makes sense. To
                        me a closure is the ability to keep a reference to a function variable
                        after the function has finished executing. That isn’t particularly
                        accurate from a technical viewpoint, but it does the job for me.

                        3. In the “Why do you want closures” section, the statement “...the
                        closure is invisible except to the singe public function of the
                        closure” is misleading: any number of functions can have closures to
                        the variables of a function. Also, if the functions that have those
                        references are public, they can be called privileged (see Crockford’s
                        article on public and private members in javascript[1]). A reference
                        to that article should be included.

                        4. A closure is a consequence of declaring one function inside another
                        using either a formal declaration, function expression or statement.
                        It’s only useful if some reference is kept of course, but the closure
                        isn’t the variable reference, it’s the ability of the “inner” function
                        to access the activation object of the outer function and its
                        variables.

                        I think you should reference the FAQ article[2] which is not only a
                        comprehensive and technically excellent article on closures, it
                        teaches an awful lot about the fundamentals of functions in general.

                        1. Douglas Crockford, Private Members in JavaScript :
                        <URL: http://javascript.croc kford.com/private.html>

                        2. Richard Cornford, et al, Javascript Closures
                        <URL: http://www.jibbering.com/faq/faq_notes/closures.html >



                        --
                        Rob

                        Comment

                        Working...