Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can storing large variables in a closure cause problems?

I have a function in which I'm using closure as follows:

function myobject() {
  var width=300,
      height=400,
      bigjsondata = { } // assume this is a big variable ~ 300k

  function obj(htmlelement) {
     // plot a graph in this htmlelement based on bigjsondata
  }

  return obj;
}

var plot1 = myobject();
plot1('#holder1');

var plot2 = myobject();
plot1('#holder2');

the variable bigjsondata contains a large dataset. The question is: does it allocate memory for bigjsondata whenever I create a variable var a = myobject() ?

Can it lead to memory problems if a lot of instances are created?

If so what is the best way to load it only once? (bigjsondata does not change)

Edit: At the end I would like myobject to be globally accessible.

like image 813
Nasir Avatar asked Apr 11 '13 17:04

Nasir


People also ask

What are the disadvantages of using closures?

Disadvantages of closures There are two main disadvantages of overusing closures: The variables declared inside a closure are not garbage collected. Too many closures can slow down your application. This is actually caused by duplication of code in the memory.

Does closure cause memory leak?

In simple terms, a closure is an inner function that has access to the outer function's scope. In the example above, largeArray is never returned and cannot be reached by garbage collector, significantly increasing its size through repeated calls of inner functions, resulting in a memory leak.

What are the advantages of using a closure?

Closures are useful because they let you associate data (the lexical environment) with a function that operates on that data. This has obvious parallels to object-oriented programming, where objects allow you to associate data (the object's properties) with one or more methods.

What are closure variables?

In JavaScript, a closure is a function that references variables in the outer scope from its inner scope. The closure preserves the outer scope inside its inner scope. To understand the closures, you need to know how the lexical scoping works first.


3 Answers

not sure what you are trying to achieve, this should provide you with some private storage on different levels:

var privateStorage = function () {
  // only 1 copy total
  var bigJsonData = {...}
  return function() {
    // 1 copy for each instance
    var instanceData = {...}
    return function() {
          // something to do many times per instance
          return something_useful
    }
  }
}(); // returns function that privatelly knows about bigJsonData

var a = privateStorage(); // a is now 1st instance of the inner-most function
var b = privateStorage(); // a and b share the SAME bigJsonData object, but use different instanceData objects

a1 = a();
a2 = a();
like image 58
Aprillion Avatar answered Sep 22 '22 08:09

Aprillion


Generally - yes, you code looks like creating a new instance for the bigjsondata each time you make a new myObject(); To get arround the issue, you can use anonymous initialization function like this:

myObject = null;

(function() {
     var bigjsondata = { ... } // construct you large object here;

     function myObjectInternal() {
         // you can access `bigjsondata` from here.
         // do not change `bigjsondata`, since it will now 
         // use the changed value in all new instances of `myObjectInternal`
     }
     myObjectInternal.prototype = {
         data: function(_) {
             // you can access `bigjsondata` from here too
         }
     };

     myObject = myObjectInternal;
})();

This will create an anonymous function that is called immediately and only once (like a singleton). Inside the function, bigjsondata is a a closure to the myObjectInternal function, which is visible only in the anonymous one. That is why you define the outer global variable myObject, to latter make it point to the myObjectInternal function/object.

Define myObjectInternal as you would have myObject and you're good to go. So, in the following code:

var instance1 = new myObject();
var instance2 = new myObject();

it will use the same bigjsondata for instance1 and instance2

like image 34
Ivaylo Slavov Avatar answered Sep 21 '22 08:09

Ivaylo Slavov


I would suggest going for an object oriented approach for this.

function obj (htmlelement)
{
    this.htmlelement = $(htmlelement);    
}

obj.prototype.htmlelement = null;
obj.prototype.bigjsondata = {};
obj.prototype.width = 300;
obj.prototype.height=400;

obj.prototype.plot = function ()
{
   var htmlelement = this.htmlelement;
   var bigjsondata = this.bigjsondata;
   var width = this.width;
   var height = this.height;
   //plot graph here;
}

var plot1  = new obj('#holder1');
var plot2 = new obj('#holder2');
plot1.plot();
plot2.plot();

Here, the same bigjsondata will be shared among all objects of obj.

like image 41
Parthik Gosar Avatar answered Sep 22 '22 08:09

Parthik Gosar