Good examples of using Closure in Javascript

Ok, I recently found out about closing in Javascript.

While I find the concept really awesome, I have yet to find a good app for them.

In all the blog posts, all the tuturials I found, I got a good explanation of what they are and how to work with them.

What I cannot find anywhere are examples that make me think: "Wow, can you do THIS with closing? Awesome !!!". All the examples that I find are purely academic, like this one.

function say667() {
  // Local variable that ends up within closure
  var num = 666;
  var sayAlert = function() { alert(num); }
  num++;
  return sayAlert;
}

var sayNumber = say667();
alert(sayNumber());

So, I was wondering if any of you could share an impressive experience with these special features.

I know this is a kind of open-ended question, but I will attribute the answer to whoever makes me WOW the most.

thank

+5
7

"" - , , , .

- , .


curry, , , .

function curry() {
    var args = Array.prototype.slice.call(arguments);
    return function(fn) {
        return function() {
            var args2 = Array.prototype.slice.call(arguments);
            return fn.apply(this,args.concat(args2));
        };
    };
}

,

, , ...

var workWithName = curry("Bubba");

... , , .


, curried

talkToName, ...

var talkToName = workWithName(function(curried_str, before, after) {
    return before + curried_str + after;
});

, talkToName, 2 , .

talkToName("Hello there ", ". How are you?"); // "Hello there Bubba. How are you?"
talkToName("", " is really super awesome.");  // "Bubba is really super awesome."

, talkToName, , workWithName, 3 .

, workWithName(), , talkToName, .


, workWithName, "Bubba" , ...

var incrementName = workWithName(function(curried_str, n) {
    var ret = '';
    for(var i = 0; i < curried_str.length; i++) {
        ret += String.fromCharCode(curried_str[i].charCodeAt() + n);
    }
    return ret;
});

, incrementName ...

incrementName(3);  // "Exeed"
incrementName(8);  // "J}jji"
incrementName(0);  // "Bubba"

, , curry() , , , .

, incrementName, , workWithName, 2 . curried.


, , 3 5.

var workWith3And5 = curry(3, 5);

,

, workWith3And5, , ...

var addNTo3And5 = workWith3And5(function(x, y, n) {
    return [3 + n, 5 + n];
});

addNTo3And5( 8 );  // [11, 13];
addNTo3And5( -4 ); // [-1, 1];

, workWith3And5, 3 5, 3 x 5, ...

var create3By5GridWithData = workWith3And5(function(x, y, data) {
    var ret = []
    for(var i = 0; i < x; i++) {
        ret[i] = [];
        for(var j = 0; j < y; j++) {
           ret[i][j] = data;
        }
    }
    return ret;
});

create3By5GridWithData( 'content' ); // [Array[5], Array[5], Array[5]]
+5

, , "" , , .

, SO.

setTimeout: fooobar.com/questions/1101023/...

: fooobar.com/questions/1101025/...

, , SO ( , , ).

, :

function slides(images) {
    var slideImages = images || [];

    // because of this closure, the variable slideImages is available
    // to the method defined in here even though the slides function
    // has already finished executing
    this.addSlide = function(url) {
        slideImages.push(url);
    }
    this.clearSlides = function() {
        slideImages = [];
    }
}

// the slideImages variable is not available out here
// it is truly private inside the clsoure
var slideshow = new slides(imgArray);
slideshow.addSlide("xxx.jpeg");
+7

, , , :

function Thing() {
  var x = 10;
  this.getX = function () {
    return x;
  }

  this.increment = function () {
    x++;
  }
}

, new Thing, getX increment, x. x Thing.

: http://javascript.crockford.com/private.html

+5

:

var getDay = (function () {
    var days = [
        'Monday',
        'Tuesday',
        'Wednesday',
        'Thursday',
        'Friday',
        'Saturday',
        'Sunday'
    ];

    return function ( n ) {
        return days[ n - 1 ];
    };
}());

, IIFE, . , IIFE. IIFE, , , IIFE .

, IIFE days, private getDay.

+5

. , Java, , .

, , -

var that = this; // that is defined outside of the function below, but is still in its
                 // lexical scope
arry.each(function(item){
   that.doSomething(item); // which means 'that' is "closed-in" to this function
});
+3

- , .

JLinx.Delegate=function() {
  var validateArg=function(arg) {
    if(typeof arg!=="string"&&typeof arg!=="function"&&arg!==null&&arg!==undefined) {
      throw new ArgumentException("arg");
    }
  };
  var funcBody;
  function prepBody(code,returnsResult) {
    var temp=code.trimLeft().trimRight();
    if(returnsResult&&temp.indexOf("return ")== -1) {temp="return "+temp;}
    if(temp.substr(temp.length-1,1)!=";") {temp+=";";}
    return temp;
  }
  function getDelegate(arg,defaultLambda,returnsResult) {
    validateArg(arg);
    if(typeof arg==="function") {return arg;}
    arg=(arg===null||arg===undefined)?defaultLambda:arg;
    if(arg.indexOf("=>")> -1) {
      var parts=arg.split("=>");
      var argList=parts[0];
      funcBody=prepBody(parts[1],returnsResult);
      argList=argList.trimLeft().trimRight()==""?"e":argList;
      argList=(argList.indexOf(",")> -1)?argList.split(","):[argList];
      switch(argList.length) {
        case 1:
          return new Function(argList[0],funcBody);
        case 2:
          return new Function(argList[0],argList[1],funcBody);
        default:
          throw new InvalidOperationException("Invalid number of arguments to action delegate.");
      }
    }
    else {
      funcBody=prepBody(arg,returnsResult);
      return new Function("e",funcBody);
    }
  }
  var factory=
    {
      actionFrom: function(arg) { return getDelegate(arg,"e => return;",false); },
      accumulatorFrom: function(arg) { return getDelegate(arg,"e, v => return v;",true); },
      comparerFrom: function(arg) { return getDelegate(arg,"l,r=>return l<r?-1:l>r?1:0;",true); },
      joinSelectorFrom: function(arg) { return getDelegate(arg,"o, i = { return { o : o, i : i }; };",true); },
      predicateFrom: function(arg) { return getDelegate(arg,"e => return true;",true); },
      selectorFrom: function(arg) { return getDelegate(arg,"e => return e;",true); }
    };
  return factory;
} ();

, , , ( LINQ-to-XML), :

var exists = myXmlElement.Any("e.name == 'foo' || e.name == 'bar';');

factory, , Sequence. , .

, .

+3

, , Javascript..

      var juice = "Mango";
    var foo = function() {
     var juice = "Apple";
  return function(){
   return juice;
}

    };
var juicebar = foo();
console.log(juice);
console.log(juicebar());
0

All Articles