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.
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.
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.
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.
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.
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();
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With