So I found this piece of code and it obviously works (as it has been in production for years):
window[someMethod] = function (tmp) {
callback({prop:"val"}, tmp);
// Garbage collect
window[someMethod] = undefined;
try {
delete window[someMethod];
}
catch (e) { }
if (head) {
head.removeChild(script);
}
// head refers to DOM head elem and script refers to some script file elem
};
Curious to know, how does it work?
How can it set itself to undefined within its body and try to
delete itself?
Does the browser know to not execute the undefined and delete until the call is finished? And how?
If the browser deletes it right away, then what happens after? Does the last line run?
Finally, do you guys see this leaking memory? If yes, how?
It's not setting itself to undefined, it's setting a reference to itself to undefined. If you think of a function as a block of code in memory, that block of code isn't deleted in this case, just the reference to it. You never explicitly delete anything in JavaScript, you simply remove references to it and leave it to the garbage collector to clean up. Note, this might not be the case for actual code, just heap objects, as its up to the engine how to treat it (interpret it, compile it, execute it on an abacus, whatever)
Based on that logic, once the function is executing, the original reference to it is no longer required as it was needed only initially to transfer execution to it.
You're misunderstanding JS evaluation as requiring a reference to it for every statement. In all likelihood, this method has been Just-In-Time compiled and is now executing just like any other non-JS function would run.
There are no apparent memory leaks in the code above.
Hopefully this is making sense.
Remember you can't ever explicitly delete something in Javascript. All you can do is remove all the references to it and so let the garbage collector remove it on the next cycle. By the end of this function, the function itself is still in memory, but there are no external references to it. Next time the GC runs, it will spot this and deallocate its memory.
window[someMethod] is simply a reference. Only the reference is deleted, not the function itself.
Once the function is done, and all reference to it are removed, garbage collection should take care of it, avoiding memory leaks.
Related
If I have the following JavaScript code:
<script id="someJS">
var boom = 'boom';
function example(){
alert(boom);
}
</script>
and then do:
$('#someJS').remove();
I can still call example() even though that JavaScript function is no longer inside the DOM... How can I remove it?
I don't want to null the actual function(s) and variables with: boom = null; example = null; as I don't always know what is inside the JavaScript file. For example the function names, variables, etc. I need to be able to remove the entirity of what was inside that script tag.
Update: For those that wanted to know the user case for this:
Basically in an app I am working on, we have custom JavaScript added for certain clients that when a button is clicked e.g. save, then checks if certain functions exist and then runs them. However because this save button is generic it means that that the custom code gets called all the time after it's added even if it's no longer relevant.
The solution we have come up with (someone had posted this as an answer but they removed it for some reason) was to namespace it all like:
DynamicJS = {
boom: 'boom',
example: function(message) {
alert(message);
}
}
And then we can just do: delete DyanmicJS;
Which removes all the functions and variables inside this namespace from the global scope, effectively binning off what the script file added.
Although I am sure this is not a perfect solution as if you had event listeners inside the file, I'm sure they would still exist!
How can I remove it? I don't want to null the actual function, as I don't always know what is inside the JS file.
You can't. Script code is executed, creates things in the JavaScript environment, and is completely disconnected from the script element that loaded it. Other than completely reloading that environment, if you don't know what the code did, you can't undo it.
Even if you could infer some of what the code did (for instance, by making a list of globals before and after), while you could remove new globals you detected (or at least set them to null or undefined, since delete doesn't work wiith globals added via function declarations or var), that doesn't tell you what event handlers, web workers, etc. the code may have hooked up.
$('#someJS').remove(); only removes the script element from the page.
By the time the element is removed, the script has already been interpreted, which means example has been added to the global scope.
To properly remove that function you could do this:
window.example = null;
However, apparently you don't want to do this, and this will result in a load of errors if there's script elsewhere that actually uses example.
An alternative could be to assign an empty function to it:
window.example = function(){};
This will prevent the "removal" from resulting in errors.
(Aside from the function not returning values when that may be expected)
Once the function has been processed, it is now part of the window's executable list of functions - regardless of if you remove the original source or not.
To remove the function entirely, try:
window['example'] = null;
However, based on your last comment:
I don't want to null the actual function, as I don't always know what is inside the JS file.
It sounds like you want to maintain reference to the function but not have it executable directly? If that's the case, you can store a reference to it and remove the original:
var _exampleBackup = window['example'];
window['example'] = null;
To call it, you can now use:
_exampleBackup();
And to restore it, if you need to:
window['example'] = _exampleBackup;
example();
That function is still in the window.
Code that you put inside a script tag will be ran when the element is created and has no value (roughly) by itself anymore. Removing the tag will not affect the document and the impact it had on it (generally).
To remove the function you need to remove the example property on the window object, which is how the function will be defined, running the code above.
$('#someJS').remove();does nothing more than removing the text from the DOM, but does nothing to the actual function (nor the file), since it is parsed and executed.
In order to delete the function, you could either set it to null or simply overwrite it with example=function(){};
JavaScript Hoisting
There is a concept in JavaScript called Hoisting. In this phase, compiler parse all JavaScript code and declares variables and function at the beginning of scope. In your case, function example and variable boom is already declared and kept in memory. When you run that method, interpreter will call that method and interpret it instead of interpreting actual JavaScript code. You are deleting script block after it went in memory. And thats why it is still executable.
Approaches to do this
1) Use object oriented approach. Add your method in a object, and when you want to delete it, delete that property by using delete.
2) Create one variable which holds a function which contains your code to execute, and set that variable undefined when you want.
I am reading this article on javascript optimization. Article
I came across this section and it tells me when a leak occurs. But I can't find what is the proper way to call it so a leak does not occur. Here is the section I am interested in.
One of the worst places to leak is in a loop, or in setTimeout()/setInterval(), but this is quite common.
Consider the following example.
var myObj = {
callMeMaybe: function () {
var myRef = this;
var val = setTimeout(function () {
console.log('Time is running out!');
myRef.callMeMaybe();
}, 1000);
}
};
If we then run:
myObj.callMeMaybe();
to begin the timer, we can see every second “Time is running out!” If we then run:
myObj = null;
The timer will still fire. myObj won’t be garbage collected as the closure passed to setTimeout has to be kept alive in order to be executed. In turn, it holds references to myObj as it captures myRef. This would be the same if we’d passed the closure to any other function, keeping references to it.
It is also worth keeping in mind that references inside a setTimeout/setInterval call, such as functions, will need to execute and complete before they can be garbage collected.
The question is: How do you do this properly so that you don't leak? Is it as simple as calling clearInterval? And does this leak once or leak once per interval
I wouldn't call this a memory leak in any fashion - it's simple garbage collection doing what it's supposed to. There is no more "proper" way to do it.
The object that was initially pointed to by myObj is still in use as long as your timer is running. A garbage collector will free it as soon as there are no more references to it. Setting myObj = null clears one reference to it, but your ongoing timers have another reference in myRef so it can not be garbage collected until ALL references to it are gone.
Yes, if you stop your timer and set myObj = null, then there will be no more references to the object and the GC will get rid of it. Keep in mind that you will need to provide access to the timerid if you want to stop the timer from the outside because no outside code can get to val where you have it stored now.
If you had lots of other data in myObj that the timer did not need access to and you were trying to allow that data to be freed while the timer continues to run, then you can either keep the same structure you have now, but clear that other data from the object (either remove the properties or set the properties to null) or you can change the structure of your code so that the recurring timer is launched with a separate function call and doesn't have to keep a reference to the object in order to call a method.
In other words, if your timer method needs access to the object, then the object is correctly kept alive by the garbage collector. If the timer method doesn't need access to the object, then you should run the recurring timer some other way that doesn't repeatedly call a method on the object - allowing the object to be garbage collected.
Is it possible to create memory leaks when coding in Javascript? and if so is this dependent on the Javascript rendering engine e.g. V8 or IE's Chakra
I seem to be getting really slow performance when iterating through large loop constructs.
Should i "delete" the variables that im not using?
var myVar = 'very very long string';
delete myVar;
In the example you've shown, unless myVar is in the global scope it will simply be garbage collected at the end of the function.
In general, you don't need to worry about memory in JavaScript. Where you do need to worry about memory is when you unintentionally create references to objects and forget about them. For example:
function buttonClick() {
var clicked = false;
document.body.addEventListener('click', function(event) {
if (clicked) return;
if (event.target.nodeName !== 'button') return;
clicked = foo();
}, true);
}
The above code is bad code to begin with (not cleaning up event listeners), but it illustrates the example of a "memory leak" in JavaScript. When buttonClick() is called, it binds a function to the click event on the <body>. Because removeEventListener is never called to unbind the listener, the memory used by the function is never reclaimed. That means that every time buttonClick() is called, a little bit of memory will "leak".
Even then, however, the amount of memory leaked is quite small and won't ever become a problem for the vast majority of use cases. Where it would likely be a problem is in server-side JavaScript, where the code is potentially run much more frequently and the process stays alive for much longer.
I've been reading about memory leakages lately and haven't yet wrapped my head around all of it and have some questions regarding my own style of writing. Specifically, I'm not really sure if the way I handle events might be a source of leaking. Consider the following code
function Wrapper(text) {
this.text = text;
this.bindHandlers();
};
Wrapper.prototype.onClick = function (e) {
alert(this.text);
};
Wrapper.prototype.bindHandlers = function () {
var t = this, div = $('<div>' + this.text + '</div>');
var reallyHugeArray = [1,2,3...]; // an array of 100000 elements for example
div.click(function (e) {
// all variables of the parent function are in scope for this function, including reallyHugeArray
t.onClick(e);
});
$(document).append(div);
};
var a = new Wrapper('testString');
// had enough fun with the Wrapper, now let's nullify it
a = null;
As you can see, I like to use an anonymous functions as the event handler so that it would be more convenient to have access to instance specific variables (in this case this.text in the onClick function) and functions. However, if I understood correctly, having an anonymous function inside a function (as is the event handler), which has access to the local scope, disables the garbage collector from removing the local variables, therefore creating a leak.
So my question is whether this method of event handling can create memory leakages and if it does, is there any way to prevent it, but still have a similarily convenient way to access the instance variables and functions?
(Off-topic: a function inside a function inside a function makes Javascript sound like Inception)
In your particular example, the anonymous click handler creates a function closure for the scope above it. That means that the values of t, div and reallyHugeArray are maintained for the life of your anonymous click handler function.
This is not a really a memory "leak", but rather memory "usage". It doesn't get worse and worse over time, it just uses the fixed amount of memory that those local varaibles t, div and reallyHugeArray occupy. This is often an advantage in javascript programming because those variables are available to the inner function. But, as you wondered, it can occasionally cause problems if you expected that memory to be freed.
In the case of references to other things (DOM objects or other JS variables), since these outer variables continue on, everything that they refer to also continues on and cannot be freed by the garbage collector. In general, this is not a big problem. Things that tend to cause problems are things that are done over and over as the web page is used or things that are done in some large loop with lots of iterations. Something only executed once like this just uses a little more memory once and from then on the memory usage of the construct is constant.
If, for some reason, you were binding this event handler over and over again, creating a new function closure every time and never releasing them, then it could be a problem.
I find this construct in Javascript very useful. I don't think of it as something to stay away from, but it is worth understanding in case you have references to really large things that you want to be freed, transient things that should be freed because you don't need them long term or you're doing something over and over again. In that case, you can explicitly set local variables to null if you won't need them in the inner function to kill their references and allow the garbage collector to do it's thing. But, this is not something you generally need to do - just something to be aware of in certain circumstances.
With objects especially, I don't understand what parts of the object run before initialization, what runs at initialization and what runs sometime after.
EDIT: It seems that parsetime is the wrong word. I guess I should have formulated the question "In the 2-pass read, what gets read the first pass and what gets read the second pass?"
A javascript file is run in a 2-pass read. The first pass parses syntax and collects function definitions, and the second pass actually executes the code. This can be seen by noting that the following code works:
foo();
function foo() {
return 5;
}
but the following doesn't
foo(); // ReferenceError: foo is not defined
foo = function() {
return 5;
}
However, this isn't really useful to know, as there isn't any execution in the first pass. You can't make use of this feature to change your logic at all.
Unlike C++, it is not possible to run logic in the Javascript parser.
I suspect that you're asking which code runs immediately and which code runs when you create each object instance.
The answer is that any code in a function that you call will only run when you call the function, whereas any code outside of a function will run immediately.
Not sure what you ask exactly so I'll just share what I know.
JavaScript functions are "pre loaded" and stored in the browser's memory which means that when you have function declared in the very end of the page and code calling it in the very beginning, it will work.
Note that global variables, meaning any variable assigned outside of a function, are not preloaded, so can be used only after being declared.
All commands outside of a function will be parsed in the order they appear.
JavaScript doesn't really have "runtime", it can only respond to events or have code executed via global timers. Any other code will be parsed and "forgotten".
While JavaScript's direct ancestor is Scheme, JavaScript didn't inherit macros, so the answer is fairly simple: there is never any code run during parse time.
Roughly speaking, Interpreter gets all variables and functions first, and then they get hoisted and executed.
For more detail, I hope these links might be helpful:
http://adripofjavascript.com/blog/drips/variable-and-function-hoisting
https://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/