How to "freeze" a constant into a closure?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • David Lee Lambert

    How to "freeze" a constant into a closure?

    Here's some JavaScript that does not do what I would like it to do:

    var x = new Object();
    var y = new Object();
    var j;
    for (j=0; j<5; j++) {
    x['f'+j] = function () { print(j); };
    }


    for (j=0; j<5; j++) {
    var jj = 0+j;
    y['f'+j] = function () { print(jj); };
    }

    x.f0(); // prints 5
    y.f0(); // prints 4

    I want object x to contain 5 functions, each of which prints a
    different value. (Actually, I'm building an HTML form with a table
    where any row can be removed by clicking a button in that row...) The
    two approaches above do not work. I've tried some tricks with eval,
    but they don't work either. Any idea on how to do this?

    --
    DLL
  • David Lee Lambert

    #2
    Re: How to &quot;freeze&qu ot; a constant into a closure?

    On Apr 2, 5:37 pm, David Lee Lambert <dav...@lmert.c omwrote:
    I want object x to contain 5 functions,  each of which prints a
    different value.  ...
    --
    DLL
    I figured out how to do it:


    function makePrintClosur e (val) {
    return function () { print(val); }
    }


    var x = new Object();
    var j;
    for (j=0; j<5; j++) {
    x['f'+j] = makePrintClosur e(j);
    }

    x.f0();

    Comment

    • Joost Diepenmaat

      #3
      Re: How to &quot;freeze&qu ot; a constant into a closure?

      David Lee Lambert <davidl@lmert.c omwrites:
      Here's some JavaScript that does not do what I would like it to do:
      >
      var x = new Object();
      var y = new Object();
      var j;
      for (j=0; j<5; j++) {
      x['f'+j] = function () { print(j); };
      }
      >
      >
      for (j=0; j<5; j++) {
      var jj = 0+j;
      y['f'+j] = function () { print(jj); };
      }
      >
      x.f0(); // prints 5
      y.f0(); // prints 4
      You're closing over global variables. You want to close over newly
      instantiated variables instead. Something like this:

      for (var j=0; j<5; j++) {
      x['f'+j] = (function(i) { return function () { print(i); } })(j);
      }

      or if you prefer:

      for (var j=0; j<5; j++) {
      x['f'+j] = (function() {
      var i = j;
      return function () { print(i);
      } })();
      }

      Note that javascript does NOT have a block scope, which is why your
      second attempt also closes over a global. Variables are function-scoped
      only.

      --
      Joost Diepenmaat | blog: http://joost.zeekat.nl/ | work: http://zeekat.nl/

      Comment

      • RobG

        #4
        Re: How to &quot;freeze&qu ot; a constant into a closure?

        On Apr 3, 8:03 am, David Lee Lambert <dav...@lmert.c omwrote:
        On Apr 2, 5:37 pm, David Lee Lambert <dav...@lmert.c omwrote:
        >
        I want object x to contain 5 functions, each of which prints a
        different value. ...
        --
        DLL
        >
        I figured out how to do it:
        >
        function makePrintClosur e (val) {
        return function () { print(val); }
        >
        }
        >
        var x = new Object();
        var j;
        for (j=0; j<5; j++) {
        x['f'+j] = makePrintClosur e(j);
        >
        }
        >
        x.f0();
        You might find the following link about implementing private
        variables and privileged functions useful:

        <URL: http://www.litotes.demon.co.uk/js_in...te_static.html >


        --
        Rob

        Comment

        • Thomas 'PointedEars' Lahn

          #5
          Re: How to &quot;freeze&qu ot; a constant into a closure?

          Joost Diepenmaat wrote:
          [...]
          IMHO this is one of the annoying things about javascript's function
          scope. If it had some additional way to creating scope that would
          probably be optimized a lot better, and written a bit clearer. For
          instance:
          >
          for (var j=0; j<5; j++) {
          let (i = j) {
          x['f'+i] = function(i) { print (i) };
          }
          }
          JavaScript[tm] does have that since version 1.7:




          PointedEars
          --
          Prototype.js was written by people who don't know javascript for people
          who don't know javascript. People who don't know javascript are not
          the best source of advice on designing systems that use javascript.
          -- Richard Cornford, cljs, <f806at$ail$1$8 300dec7@news.de mon.co.uk>

          Comment

          • Joost Diepenmaat

            #6
            Re: How to &quot;freeze&qu ot; a constant into a closure?

            Thomas 'PointedEars' Lahn <PointedEars@we b.dewrites:
            Joost Diepenmaat wrote:
            >[...]
            >IMHO this is one of the annoying things about javascript's function
            >scope. If it had some additional way to creating scope that would
            >probably be optimized a lot better, and written a bit clearer. For
            >instance:
            >>
            > for (var j=0; j<5; j++) {
            > let (i = j) {
            > x['f'+i] = function(i) { print (i) };
            > }
            > }
            >
            JavaScript[tm] does have that since version 1.7:
            >
            http://PointedEars.de/es-matrix/#l
            Hah, nice!

            I really should read up on those newer JavaScript versions, but
            unfortunately 99% of my current JS work is supposed to run on all the
            "popular" browsers, not just Mozilla.

            Cheers,
            Joost.

            --
            Joost Diepenmaat | blog: http://joost.zeekat.nl/ | work: http://zeekat.nl/

            Comment

            Working...