JavaScript garbage collection when variable goes out of scope - javascript

Does JavaScript support garbage collection?
For example, if I use:
function sayHello (name){
var myName = name;
alert(myName);
}
do I need to use "delete" to delete the myName variable or I just ignore it?

no.
delete is used to remove properties from objects, not for memory management.

JavaScript supports garbage collection. In this case, since you explicitly declare the variable within the function, it will (1) go out of scope when the function exits and be collected sometime after that, and (2) cannot be the target of delete (per reference linked below).
Where delete may be useful is if you declare variables implicitly, which puts them in global scope:
function foo()
{
x = "foo"; /* x is in global scope */
delete x;
}
However, it's a bad practice to define variables implicitly, so always use var and you won't have to care about delete.
For more information, see: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Operators/Special_Operators/delete_Operator

Ignore it - after the sayHello function completes, myName falls out-of-scope and gets gc'ed.

You don't need to do anything Ted, no need to delete this variable.
Refer: http://www.codingforums.com/archive/index.php/t-157637.html

As others mentioned, when the function exits then your variable falls out of scope, as it's scope is just within the function, so the gc can then clean it up.
But, it is possible for that variable to be referenced by something outside the function, then it won't be gc'ed for a while, if ever, as it is still has a reference to it.
You may want to read up on scoping in javascript:
http://www.webdotdev.com/nvd/content/view/1340/
With closures you can create memory leaks, which may be the problem you are trying to deal with, and is related to the problem I had mentioned:
http://www.jibbering.com/faq/faq_notes/closures.html

Related

Avoid declaring variables on scroll?

var variableOne;
var variableTwo;
var variableThree;
function veryInterestingFunction() {
var variableFour;
if(a){
variableFour = 'Good';
}
else {
variableFour = 'Decent';
}
console.log(variableFour);
}
$(window).on('scroll', function(){
veryInterestingFunction();
});
Here I have some variables in the global scope, a function declaring a variable and assigning a value to it, and calling this function on scroll.
This way on every scroll you are going to declare the "variableFour" which is not a good practice, right?
However I don't want to crowd the global scope with unnecessary variables and also can't use an IIFE. Is there a "best practice" way to declare the variable outside the function and still only possible to use it inside the scope of that function ?
http://jsfiddle.net/2jyddwwx/1/
to declare the variable outside the function and still only possible to use it inside the scope of that function ?
I guess, that's impossible
When I don't want to crowd the global scope, I will declare one global object, for example App = {}, and instead of global variables, I use it's properties.
App.variableOne;
App.variableTwo;
App.variableThree;
Or you can use classes in ES6
I don't think there's anything wrong with your code sample, I seriously doubt variable declaration is ever going to slow down your code. I'd definitely only start to worry about this kind of thing when you're absolutely certain it's causing issues (it won't), otherwise it might be wasted effort.
If you really want to optimize this, one thing you might be able to do is debouncing the veryInterestingFunction calls - that is if you don't necessarily need to respond to every single scroll event (depends on your logic).
As per your question, IIFE/function closure is essentially the only way to limit scope in JavaScript that I know of, so if you can't use that, I don't see any other option.
There is no problem in declaring an empty variable into your scope. If it is not global, it belongs to the scope.
And there is no need to fear for performance. If you declare variables within your scope, the Javascript garbage collector will empty that for you. Take a read at this article

Javascript delete statement

Q: I am trying to work out why there is a delete statement in this code?
My assumption is foo will be dereferenced once statement has finished executing therefore would be no need to explicitly do it.
(function () {
var foo = globalObject;
foo.bar = function () {
//code here
}
delete foo;
}());
What is going on here?
See this article on when To and Not To use the delete operator.
This does not appear to be a proper use.
Local variables cannot be deleted as they are marked internally with the DontDelete attribute. There are occasions when you might want to clear a local variable (if you want to release any memory used by it and the scope may survive indefinitely in a closure), but you don't use the delete operator for this purpose - you can just set it to null.
In normal functions that don't create closures, any local variables will simply be garbage collected when the function completes and if there are no other references to their data in other code, that data will be freed by the garbage collector.
The only time you need to worry about clearing references to data is when you have a scope that will exist for a long duration of time (closure or global) and you no longer need that data and it's useful to free up its memory usage.
FYI, the most common use of the delete operator is to remove a property from an object as in:
var foo = {x: 1, y: 2};
delete foo.x;

But var it is not for local variable?

This is my code :
var markers={};
example();
function example() {
var myFunct = function () {
alert("hello");
};
markers["myIndex"] = myFunct;
}
markers["myIndex"]();
as you can see, myFunct is "var" (so, when example() finish, it will be destroyed, because it is local). But in fact, accessing to markers["myIndex"](), the function is referenced, and I can access to it. Why?
This doesn't work the way you expect it to. In other words, when example() finishes, myFunct will not be destroyed because there is still a reference to that function in a variable from an outer scope, markers.
The only way it would be 'destroyed' is if nothing else referenced it at the end of example() or if only variables with equal or lower scope referenced it, provided those variables also followed the same rules and were not referenced from outer variables.
In JavaScript, functions are objects just like other objects. When you do this:
var myFunct = function () {
alert("hello");
};
...you're creating a function and assigning a reference to that function to the variable myFunct. Then when you do this:
markers["myIndex"] = myFunct;
...you're assigning another reference to that function to markers["myIndex"]. So regardless of anything else that might happen to the myFunct variable, because markers["myIndex"] still has a reference to the function, the function is kept in memory.
But separately, there's a more subtle misunderstanding in your question as well: You've said:
myFunct is "var" (so, when example() finish, it will be destroyed, because it is local)
That's not true in JavaScript. In JavaScript, local variables are actually properties of a hidden object, called (deep breath) the variable binding object of the execution context (let's just call it the "variable object"). This object is associated with the particular call to example: It's created when the call to example is executed. Now, in the normal course of things, when example returns, if nothing has any outstanding reference to the variable object, then you're quite correct that it is eligible for garbage collection. But in your case, something does have a reference to the variable object: The function you created. When you create a function, it receives an implicit reference to the variable object for the context in which it was created, and it keeps that reference for as long as the function exists. So even though the function you're creating doesn't refer to anything in the variable object for the call to example, it has that reference to it nevertheless, and the variable object cannot be reclaimed until or unless nothing has a reference to the function anymore. This is how closures work. The foregoing text notwithstanding, closures are not complicated, they're really, really simple when you understand how they work.
(I'll just note here that some JavaScript engines introspect the code sufficiently that they can reclaim variable objects even when there are outstanding closures that refer to them. Specifically, if the closures [functions] don't actually use any of the variable object's properties, and they don't use eval, then the engine may be able to release the variable object. Chrome's V8 engine does this, for instance. But that's a runtime optimization; the concept is as described above.)
Because you have assigned it to the global variable markers from within your example function.
you're assigning a reference to the function object to a higher scope (if not global scope) object. So while myFunct would be garbage collected, the function is not, since there is another reference to it in the markers object.
A reference from var myFunct to the actual function object (function() { ... }) will indeed be destroyed. But the object itself will not, as it is referenced by a markers field. Once there are no live references to the function object from live JS objects, this function object will be eligible for garbage collection.

How can I set a Global Variable from within a function

How can I set a Global Variable from within a function?
$(document).ready(function() {
var option = '';
$("[name=select_option_selected]").change(function() {
var option = $(this).val();
alert(option); // Example: Foo
});
alert(option); // Need it to alert Foo from the above change function
});
Declare it outside the scope of your jQuery onready
var option = '';
$(document).ready(function() {
$("[name=select_option_selected]").change(function() {
option = $(this).val();
alert(option); // Example: Foo
});
alert(option); //This will never be "Foo" since option isn't set until that select list changes
});
if you want to initialize this to the current selected value try this:
var option = "";
var $select_option_selected = null;
$(function() {
$select_option_selected = $("[name='select_option_selected']")
$select_option_selected.change(function() {
option = $(this).val();
});
option = $select_option_selected.val();
});
The Bad Way
As the other answers point out, it's not a good idea to create global variables. And as they point out, you can create a global variable by:
Declaring variable outside of all functions
Initializing your variable without the var keyword
Or, declaring it as a property of the window object: window.options = 'blah';
Using jQuery's Data() Method
But there is a better way of creating a globally accessible value using jQuery (and other libraries). In jQuery, use the data() method to store values associated with DOM elements:
// store 'blah' at document root
$(document).data('mysite.option', 'blah');
// retrieve value
alert($(document).data('mysite.option'));
Notice "mysite"... it is a good idea to namespace your data keys for the same reason it is good to namespace global variables in javascript.
$(document).ready(function() {
var option = '';
$("[name=select_option_selected]").change(function() {
option = $(this).val(); //no declaration of new variable, JavaScript goes to what encloses the function
alert(option); // Example: Foo
});
alert(option); // Need it to alert Foo from the above change function
});
Are you sure you want to? global variables are generally to be avoided. In the browser, window is the global object, so if you do window.option = ..., then option will be available globally.
I highly recommend naming a global variable something more unique than "option", to avoid clobbering existing stuff.
Another option, which I also don't recommend: leave off var
myvariable = 'foo';
If myvariable has never been delcared before, it will be declared as a property on window, making it global. This is generally considered to be (very) bad practice however.
You can use the window. prefix to access a global variable from within the scope of a function
window.option = ...;
Two approaches not mentioned by anybody else, applicable when you: 1. don't have access to the global LexicalEnvironment,10.2.3 and 2. are trying to write code that you wish to support systems wherein a direct reference to the global object15.1 (such as window in the HTML DOM, or GLOBAL in Node[1]) isn't guaranteed:
Make an indirect15.1.2.1.1 call to eval, by wrapping it in a superfluous PrimaryExpression, thus: (1,eval)(...) (the digit and comma operator are meaningless) … and then calling the result thereof. This forces the code to be run in the global execution context.10.4.2
We can then declare10.5 a new variable in the global lexical environment, as suggested above; or, for that matter, do anything else that we desire within that environment:
function global_define(ident, value){
(1,eval) ("var "+ident+"; (function(v){ "+ident+" = v })") (value) }
To be less round-about (and, to boot, avoid the FUD-ridden eval call), we can directly access the global object and set a property4.2 on it, which will then be available as a global variable elsewhere in our code.[2]
Instead of taking the eval approach above and gaining access to the global object via code we've written in the global context, it turns out we can access the global object as the this value10.4.3 within any function that is called with null:
var global = (function(){ return this }).call(null)
global[ident] = value
Phew.
Okay, more reading, for those of you who haven't fainted from specification links and eval calls, yet:
#kangax covers all of the bases quite thoroughly. Seriously, read that if you have any questions I haven't answered here (including those relating to the all-important idiosyncrasies browser support!)
Obviously, the relevant sections of the ECMAScript 5 specification itself, to get an idea for how things are intended to work in an ideal world. No, really though; I know that specifications are a scary idea, but the ES (“JavaScript”) specifications are one of the easiest-to-read and most comprehensible specs I've ever seen. They're truly excellent. Of immediate note, and in no particular order,
10.4, Establishing an Execution Context: Covers how ‘global code’ and ‘eval code’ are handled, specifically.
10.2, Lexical Environments: These describe “where variables are stored.” (The ‘Global Environment’ of interest is one of these.)
10.1, Types of Executable Code: Covers what ‘global code’ and ‘Program’s are.
15.1, The Global Object: Unfortunately, far less relevant than its title makes it sound. Still worth a skim.
[1]: The discussion in other answers, suggesting that exports in Node.js and other CommonJS-compliant systems is somehow related to the global object, about which this question asks, is misleading. In terms of system-design, one might be better suited to using their environment's module tools than poking around on the global object … but that's a discussion for another Stack Overflow post. (=
[2]: For those of you following along in the spec, it's harder to demonstrate that property-members of the global object are accessible as Identifier dereferences. Start with 10.2.1.2 Object Environment Records and 10.2.3 The Global Environment to understand how the global object is linked to an environment, then hop on over to 18.12.3, 18.12.2, and 18.12.1 in that order, collectively describing [[Get]] on the global object.
Nota bene: At no point in this elaboration did I suggest that doing either of these things was a good idea. Or, for that matter, that interacting with the global scope at all is a good idea. Of no relation to the question at hand, but proffered to soothe my own conscience, I add that I wrap all of my own code in a IIFE beginning immediately at the top of the file; this, along with religious application of the var keyword, ensures that I never interact with JavaScript's handling of the global object at all. A huge mess, avoided. You should do that. I said so. I'm smart. (;
just declare a global object
var obj={};
function my_function()
{
obj['newVariable'] = 'someValue';
}
in this way i achieved global variable.
http://jsfiddle.net/Kba5u/
var foo = 'bar';
function changeFooToBaz(){
foo = 'baz';
}
// changeFooToBaz();
console.log(foo); #=> 'bar'
Now, uncomment the call to changeFooToBaz:
var foo = 'bar';
function changeFooToBaz(){
foo = 'baz';
}
changeFooToBaz();
console.log(foo); #=> 'baz'
changeFooToBaz has indeed changed the contents of foo, a variable that was declared at a higher scope than the function.

Should I encapsulate blocks of functionality in anonymous JavaScript functions?

My intuition is that it's a good idea to encapsulate blocks of code in anonymous functions like this:
(function() {
var aVar;
aVar.func = function() { alert('ronk'); };
aVar.mem = 5;
})();
Because I'm not going to need aVar again, so I assume that the garbage collector will then delete aVar when it goes out of scope. Is this right? Or are interpreters smart enough to see that I don't use the variable again and clean it up immediately? Are there any reasons such as style or readability that I should not use anonymous functions this way?
Also, if I name the function, like this:
var operations = function() {
var aVar;
aVar.func = function() { alert('ronk'); };
aVar.mem = 5;
};
operations();
does operations then necessarily stick around until it goes out of scope? Or can the interpreter immediately tell when it's no longer needed?
A Better Example
I'd also like to clarify that I'm not necessarily talking about global scope. Consider a block that looks like
(function() {
var date = new Date(); // I want to keep this around indefinitely
// And even thought date is private, it will be accessible via this HTML node
// to other scripts.
document.getElementById('someNode').date = date;
// This function is private
function someFunction() {
var someFuncMember;
}
// I can still call this because I named it. someFunction remains available.
// It has a someFuncMember that is instantiated whenever someFunction is
// called, but then goes out of scope and is deleted.
someFunction();
// This function is anonymous, and its members should go out of scope and be
// deleted
(function() {
var member;
})(); // member is immediately deleted
// ...and the function is also deleted, right? Because I never assigned it to a
// variable. So for performance, this is preferrable to the someFunction
// example as long as I don't need to call the code again.
})();
Are my assumptions and conclusions in there correct? Whenever I'm not going to reuse a block, I should not only encapsulate it in a function, but encapsulate it in an anonymous function so that the function has no references and is deleted after it's called, right?
You're right that sticking variables inside an anonymous function is a good practice to avoid cluttering up the global object.
To answer your latter two questions: It's completely impossible for the interpreter to know that an object won't be used again as long as there's a globally visible reference to it. For all the interpreter knows, you could eval some code that depends on window['aVar'] or window['operation'] at any moment.
Essentially, remember two things:
As long as an object is around, none of its slots will be magically freed without your say-so.
Variables declared in the global context are slots of the global object (window in client-side Javascript).
Combined, these mean that objects in global variables last for the lifetime of your script (unless the variable is reassigned). This is why we declare anonymous functions — the variables get a new context object that disappears as soon as the function finishes execution. In addition to the efficiency wins, it also reduces the chance of name collisions.
Your second example (with the inner anonymous function) might be a little overzealous, though. I wouldn't worry about "helping the garbage collector" there — GC probably isn't going to run in the middle that function anyway. Worry about things that will be kept around persistently, not just slightly longer than they otherwise would be. These self-executing anonymous functions are basically modules of code that naturally belong together, so a good guide is to think about whether that describes what you're doing.
There are reasons to use anonymous functions inside anonymous functions, though. For example, in this case:
(function () {
var bfa = new Array(24 * 1024*1024);
var calculation = calculationFor(bfa);
$('.resultShowButton').click( function () {
var text = "Result is " + eval(calculation);
alert(text);
} );
})();
This results in that gigantic array being captured by the click callback so that it never goes away. You could avoid this by quarantining the array inside its own function.
Anything that you add to the global scope will stay there until the page is unloaded (unless you specifically remove it).
It's generally a good idea to put variables and function that belong together either in a local scope or in an object, so that they add as little as possible to the global namespace. That way it's a lot easier to reuse code, as you can combine different scripts in a page with minimal risks for naming collisions.

Categories

Resources