1

I am trying to use closure for storing and retrieving variable at the same time.

I am using JSONP and callback to the function

http://freegeoip.net/json/?callback=geoIPInfo

Closure

function geoIPInfo(newGeoData) {
    var geoInfo;
    if (newGeoData) {
        geoInfo = newGeoData;
    }
    var provideGeoData = function () {
        return geoInfo;
    };

    return provideGeoData();
}

I want firstly to store data and than retrieve last saved data from the closure using simple call like that

geoIPInfo()

If argument provided it will set new info otherwise it will return existing one.

But in my case data is set successfully, but when I try to get set data I get undefined

 $("#super_button").click(function (e) {
            alert(geoIPInfo());
            e.preventDefault();
        });

What is wrong with my closure understanding ? Please explain.

Thank you.

  • What's wrong is that each time you call geoIPInfo you create a new closure, you need the function to return the function object and not a function call and the use that function object as a regular function – nottu Nov 26 '16 at 18:40

2 Answers2

2

This will work. The idea here is we create a function that returns a function with that accepts a parameter and we store geoInfo in a closure to keep it value. Idk if that makes sense, if you need a better explanation I can give it another try :)

var geoIPInfo  = function() {
    var geoInfo;
    var provideGeoData = function (newGeoData) {
        if (newGeoData) {
            geoInfo = newGeoData;
        }
        return geoInfo;
    };
    return provideGeoData;
}();
nottu
  • 369
  • 1
  • 12
  • It works, thank you, could you explain what was the error as detailed as you can, thanks. –  Nov 26 '16 at 18:39
  • Here's a link to a book chapter that explains it way better than I could. https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20%26%20closures/ch5.md#nitty-gritty – nottu Nov 26 '16 at 18:42
0

Each time you call geoIPInfo(), you're re-declaring the local variable geoInfo. You'll want to declare geoInfo once, and have it accessible to geoIPInfo() via a closure:

//Create a closure
var geoIPInfo = (function(){ 

  //Private variable, available via closure
  var geoInfo;

  function geoIPInfo(newGeoData) {
   
    if (newGeoData) {
      geoInfo = newGeoData;
    }
 
    var provideGeoData = function () {
      return geoInfo;
    };

    return provideGeoData();
  }

  return geoIPInfo;
})();

alert(geoIPInfo()); //undefined
geoIPInfo('Some Data');
alert(geoIPInfo()); //'Some Data'

Here, we're creating a closure using an Immediately-Invoked Function Expression (IIFE).

Community
  • 1
  • 1
Alex K
  • 1,937
  • 11
  • 12