Javascript: named closure and memory management - javascript

I'm trying to know more about memory management in JS and I have some question about closures.
Case 1:
// Suppose that object var is capable to emit events
var object = new EventEmitter();
object.addEventListener('custom-event', function callback(event) {
object.removeEventListener('custom-event', callback);
object = null;
//Do some heavy computation like opening a specific view or somehthing similar
var heavy_window = new HeavyWindow();
heavy_window.open();
});
Case 2:
// Suppose that object var is capable to emit events
var object = new EventEmitter();
object.addEventListener('custom-event', callback = function(event) {
object.removeEventListener('custom-event', callback);
object = null;
//Do some heavy computation like opening a specific view or somehthing similar
});
My questions are:
Case 1:
Is correct to think that the object remains in memory until the heavy_window is not nulled?
Nulling the object var inside the closure can help gc?
Case 2:
Naming a closure in this way ...addEventListener(callback = function() {}) instead of ...addEventListener(function callback() {}) can cause a memory leaks? Declaring callback = function() {} will cause a global hidden variable?
Note, I don't need examples in jQuery or using other framework. I'm interested to know more in JavaScript vanilla.
Thank you in advance.

I don't think the details for garbage collecting is specified in the ES specification. However in most interpreters, objects will usually be garbage-collected once there doesn't exist any references to the object or not accessible, or scheduled at a later time.
In case 1, heavy_window might have access to the original new EventEmitter (event often has references to the event target) if you pass the event object into HeavyWindow, and thus your new EventEmitter() might not be garbage-collected until all references to your heavy_window are gone. If not, then your new EventEmitter will be garbage-collected at some point in the future.
In case 2, assigning the callback function to a global variable callback will not change anything because the callback function do not have any reference to the actual new EventEmitter object you have created. (Again, unless event has a reference to the new EventEmitter object you have created.)
In reality things might be a little different since garbage collectors in browsers are fairly complex. At what time the interpreter decides to collect the garbage is really up to it, but the bottom line is that it will only do it when all references to an object are gone.
Memory management usually isn't really a concern is JavaScript and you shouldn't need to be thinking about it most of the time. You will know it if there is a memory leak and able to detect it by using developer tools provided by the browser.

Related

Prototypal Inheritance Issues in JavaScript

I have some questions about my prototypal inheritance pattern that I am using for my app. First of all take a look at the pattern that I am using;
const myObjectProto = (function() {
const proto = Object.create( parentProto );
// private variables
let title = 'Some String';
// private functions
const addEmoticon = function() {
return title + ' ';
}
proto.getTitle = function() {
return addEmoticon();
}
return proto;
})();
And when I want to use it, I will use it like below:
const firstObject = Object.create( myObjectProto );
const secondObject = Object.create( myObjectProto );
// call a public function
firstObject.getTitle();
secondObject.getTitle();
My first question is this: assume that we are creating 100 objects from its corresponding proto; As far I know title is shared among them. That means if a function change it, it will be changed for all created objects. I am a little worried about the memory in this case. Do I use memory efficient with this pattern? Can someone clarify how Object.create treats with title?
My second question is about the memory leak; Let say that we want to set the firstObject to null;
firstObject = null;
Based on the fact that we have shared variables like title and even proto, I think it does nothing and I have memory leak. Am I right? If this is true, how can I fix it?
title is a local variable. It will exist as long as some code can access it. It will only exists once, as the IIFE only executes once, thus only one variable gets created. The function inside addEmoticon can access title, in other words it closures over it. As it is a local itself, it will also only exist as long as it can be accessed. It gets accessed inside the function stored inside proto.getTitle, which again closures over addEmoticon. proto.getTitle exists as long as proto can be accessed. As the value of proto gets stored inside the global variable const myObjectProto, it can always be accessed thus it will live forever (as well as every value that can be accessed through it, e.g. title).
Do I use memory efficient with this pattern?
Well, you allocate a few bytes once. Assuming that you have a few Megabytes available, thats not a lot.
As far I know title is shared among them
Yes.
Based on the fact that we have shared variables like title and even proto, I think it does nothing and I have memory leak.
You loose the reference to the instance stored in firstObject, thus making it viable for garbagge collection. That might free a few bytes. As the prototype is still available via secondObject and myObjectProto, it will continue living.
I have memory leak. Am I right?
A memory leak is a noticible amount of memory, that is still allocated although the values in it don't need to be used anymore. Under the assumption that you want to work with secondObject, and create new instances from myObjectProto, everything you've stored is still needed. Your code is perfectly fine.

When instantiating a new class in javascript, what's the harm in not assigning it to a variable?

So, say I have a class (not a great example but it works for this purpose):
function Apple (type) {
this.getInfo = function() {
alert('this apple is green');
};
this.getInfo();
}
and I want to create an instance of it, so I would typically do:
var apple = new Apple();
However, in my scenario, because the instance will execute immediately, I don't need the variable, so I just want to do:
new Apple();
which I know is possible, but what I don't know is what javascript will do behind the scenes. Will it create a memory reference anyway? Will it put some token into global variables? Or does it just run a one time executing class instance?
essentially, I'm asking what the harm in just using "new Apple();" is.
Update
Since this is clearly too ambiguous to get the advice i was looking for let me be more specific. At my company we use a standard classing structure for javascript files simply for consistency. This is the structure i'm talking about (mind you uses the class design from http://ejohn.org/blog/simple-javascript-inheritance/):
MyClassName = Class.extend({
init: function (/*param1, param2, etc*/) {
// this method is called immediately when the class is instantiated.
},
destroy: function () {
// this is your clean up method.
}
});
There are times when MyClassName will not need to be assigned to a variable simply because the intent is for the init method to start the whole thing, so short of lint picking up the usage of "new MyClassName();" to be an error what will core Javascript do is my ultimate question.
Most JS linters will flag instantiating a class without assigning it to a variable or property, because it indicates that either:
You made a mistake, and actually need a reference, or
You're calling the constructor for its side-effects (as is the case here), in which case you'd be better off calling a function instead.
In the latter case, it is likely (though it depends on the JS environment) that you are allocating memory you won't use by instantiating an object you don't reference. It's also (though this is opinion) usually a Bad Idea to have side effects in your constructor, as they undermine developer expectations about what creating an instance will do, and they can lead to hard-to-find bugs. It's usually simpler to put the side-effect code in a method and call it:
function Apple (type) {
this.getInfo = function() {
alert('this apple is green');
};
}
var a = new Apple();
a.getInfo();
People have already addressed why you shouldn't so I'll say what actually happens. Since your object uses this a new memory reference will be created. Assuming you don't pass that reference to anything (i.e., store a reference to the object in another object or in a closure context) and it doesn't reference any external, persistent values (anything in a closure context that is used elsewhere) then it will be collected during the next garbage collection cycle.
This article specifically talks about V8's memory model but most Javascript engines follow a similar model.
TL;DR It's not considered good practice but assuming you don't store any references to the new object, you won't be any worse for wear.

Do we manually need to clean up unreferenced variables in a closure?

I'm reading this article (http://javascript.info/tutorial/memory-leaks#memory-leak-size) about memory leaks which mentions this as a memory leak:
function f() {
var data = "Large piece of data";
function inner() {
return "Foo";
}
return inner;
}
JavaScript interpreter has no idea which variables may be required by
the inner function, so it keeps everything. In every outer
LexicalEnvironment. I hope, newer interpreters try to optimize it, but
not sure about their success.
The article suggests we need to manually set data = null before we return the inner function.
Does this hold true today? Or is this article outdated? (If it's outdated, can someone point me to a resource about current pitfalls)
Modern engines would not maintain unused variables in the outer scope.
Therefore, it doesn't matter if you set data = null before returning the inner function, because the inner function does not depend on ("close over") data.
If the inner function did depend on data--perhaps it returns it--then setting data = null is certainly not what you want to, because then, well, it would be null instead of having its original value!
Assuming the inner function does depend on data, then yes, as long as inner is being pointed to (referred to by) something, then the value of data will have to be kept around. But, that's what you are saying you want! How can you have something available without having it be available?
Remember that at some point the variable which holds the return value of f() will itself go out of scope. At that point, at least until f() is called again, data will be garbage collected.
The general rule is that you don't need to worry about memory and leaks with JavaScript. That's the whole point of GC. The garbage collector does an excellent job of identifying what is needed and what is not needed, and keeping the former and garbage collecting the latter.
You may want to consider the following example:
function foo() {
var x = 1;
return function() { debugger; return 1; };
}
function bar() {
var x = 1;
return function() { debugger; return x; };
}
foo()();
bar()();
And examine its execution in Chrome devtools variable window. When the debugger stops in the inner function of foo, note that x is not present as a local variable or as a closure. For all practical purposes, it does not exist.
When the debugger stops in the inner function of bar, we see the variable x, because it had to be preserved so as to be accessible in order to be returned.
Does this hold true today? Or is this article outdated?
No, it doesn't, and yes, it is. The article is four years old, which is a lifetime in the web world. I have no way to know if jQuery still is subject to leaks, but I'd be surprised if it were, and if so, there's an easy enough way to avoid them--don't use jQuery. The leaks the article's author mentions related to DOM loops and event handlers are not present in modern browsers, by which I mean IE10 (more likely IE9) and above. I'd suggest finding a more up-to-date reference if you really want to understand about memory leaks. Actually, I'd suggest you mainly stop worrying about memory leaks. They occur only in very specialized situations. It's hard to find much on the topic on the web these days for that precise reason. Here's one article I found: http://point.davidglasser.net/2013/06/27/surprising-javascript-memory-leak.html.
Just in addition to to #torazaburo's excellent answer, it is worth pointing out that the examples in that tutorial are not leaks. A leak what happens when a program deletes a reference to something but does not release the memory it consumes.
The last time I remember that JS developers had to really worry about genuine leaks was when Internet Explorer (6 and 7 I think) used separate memory management for the DOM and for JS. Because of this, it was possible to bind an onclick event to a button, destroy the button, and still have the event handler stranded in memory -- forever (or until the browser crashed or was closed by the user). You couldn't trigger the handler or release it after the fact. It just sat on the stack, taking up room. So if you had a long-lived webapp or a webpage that created and destroyed a lot of DOM elements, you had to be super diligent to always unbind events before destroying them.
I've also run into a few annoying leaks in iOS but these were all bugs and were (eventually) patched by Apple.
That said, a good developer needs to keep resource management in mind when writing code. Consider these two constructors:
function F() {
var data = "One megabyte of data";
this.inner = new function () {
return data;
}
}
var G = function () {};
G.prototype.data = "One megabyte of data";
G.prototype.inner = function () {
return this.data;
};
If you were to create a thousand instances of F, the browser would have to allocate an extra gigabyte of memory for all those copies of the huge string. And every time you deleted an instance, you might get some onscreen jankiness when the GC eventually recovered that ram. On the other hand, if you made a thousand instances of G, the huge string would be created once and reused by every instance. That is a huge performance boost.
But the advantage of F is that the huge string is essentially private. No other code outside of the constructor would be able to access that string directly. Because of that, each instance of F could mutate that string as much as it wanted and you'd never have to worry about causing problems for other instances.
On the other hand, the huge string in G is out there for anyone to change. Other instances could change it, and any code that shares the same scope as G could too.
So in this case, there is a trade-off between resource use and security.

Could using 'self' inside a closure lead to a memory leak?

If I have a function within an object (a Backbone model in my case)...
doIt: function () {
var self = this,
result = null;
this.doMagic(function(){
result = self.doWizardry();
});
self = null;
return result
}
...do I need to set self as null as I've done here, in order to avoid memory leaks?
Bonus question, will the closure's reference to 'result' cause a memory leak too?
Any advice on improving the efficiency of this type of structure would be much appreciated!
(Hopefully obvious that this is not a real function, just illustrative)
Thanks!
No. In fact, setting self to null before this.doMamgic() is called will also ruin the variable self such that this.doMagic() won't be able to use it because its value will have been cleared when this.doMagic() is actually trying to use it some time later.
Self references in Javascript do not by themselves lead to memory leaks. The GC is smart enough to detect that. If a whole object is unreachable by other JS, it doesn't matter how many references the object has to itself inside the object.
I see no particular reason in this code why using the variable self would lead to a memory leak and doing something like this is a well-established pattern for storing state that a callback can use (just like you're trying to do).
As for general advice, the point of the doIt() function looks like it has issues. You appear to be trying to return the result value that was set by this.doMagic(), but this.doMagic() is not called while doIt() is executing, thus result will NEVER have a value when doIt() returns.
So, this whole structure appears flawed. To know what to recommend would require understand what you're trying to accomplish and how you are calling/using this code which you have not disclosed.

Does this javascript pattern encourage memory leaks?

I am finding myself rather confused regarding javascript garbage collection and how to best encourage it.
What I would like to know is related to a particular pattern. I am not interested in whether the pattern itself is considered a good or bad idea, I am simply interested in how a browsers garbage collector would respond, i.e would the references be freed and collected or would it cause leaks.
Imagine this pattern:
TEST = {
init : function(){
this.cache = {
element : $('#element')
};
},
func1 : function(){
this.cache.element.show();
},
func2 : function(){
TEST.cache.element.show();
},
func3 : function(){
var self = this;
self.cache.element.show();
},
func4 : function(){
var element = this.cache.element;
element.show();
}
func5 : function(){
this.auxfunc(this.cache.element);
}
auxfunc1 : function(el){
el.show();
}
func6 : function(){
var el = getElement();
el.show();
}
getElement : function(){
return this.cache.element;
}
}
Now imagine that on page load TEST.init() is called;
Then later at various times the various functions are called.
What I would like to know is if caching elements or objects or anything else upon initialization and referring to them throughout the lifetime of an application, in the manner shown above, effects a browsers garbage collector positively or negatively.
Is there any difference? Which method best encourages garbage collection? Do they cause leaks? Are there any circular references? if so where?
This code, in itself, shouldn't cause any memory leaks. Especially not in modern browsers. It's just an object, like you have tons of others in any script. It all depends on where, how, and how long you reference it.
The basic rule is that, whenever an object is no longer referenced anywhere in the code (directly/by variable or indirectly/ through closure accessing a scope), the GC will flag and swipe.
If you use the above code, and then assign something else to TEST the object literal it referenced could be GC'ed, if no other variable references the original object.
Of course, predicting memory leaks in JS is an inexact science. In my experience, they're not nearly as common as some would have you believe. Firebug, Chrome's console (profiler) and IE debugger get you along a long way.
Some time ago I did some more digging into this matter resulting in this question. Perhaps some links, and findings are helpful to you...
If not here's a couple of tips to avoid the obvious leaks:
Don't use global variables (they don't actually leak memory permanently, but do so, for as long as your script runs).
Don't attach event handlers to the global object (window.onload ==> leaks mem in IE <9 because the global object is never fully unloaded, hence the event handler isn't GC'ed)
Just wrap your script in a huge IIFE, and use strict mode whenever possible. That way, you create a scope that can be GC'ed in its entirety on unload.
Test, test and test again. Don't believe every blogpost you read on the subject! If something was an issue last year, that needn't be the case today. This answer might not be 100% accurate anymore by the time you read this, or because just this morning some miracle-patch for JS GC'ing was written by erm... Paris Hilton or some other alien life-form.
Oh, and to answer your in-comment question: "But what concerns me is if each time i call this.cache.element, is it creating a new reference within that functions scope ON TOP of the original cache reference which will not be garbage collected?"
The answer is no. Because this will reference the TEST object, and the init function assigns the object a property cahche, that in itself is another object literal with 1 property referencing a jQ object. That property (cache) and all that is accessible through it will sit in memory right until you either delete TEST.cache or delete TEST. if you were to create var cahce = {...}; that object would be GC'ed when the ini function returns, because a variable cannot outlive its scope, except for when you're using closures and exposing certain variables indirectly.

Categories