Does javascript Garbage Collector dispose global variables? - javascript

I'm confused about this since I've seen several different comments. I'm reading a javascript book where it mentions that setting global variables to null is good practice (assuming there are no other references) and the GC reclaims memory for this variable on it's next sweep. I've seen other comments that say global variables are never disposed by the GC.
Also when programming javascript in a OOP structure, what happens if I have something like this (where game is in the global context):
var game = {};
game.level = 0;
game.hero = new hero();
//do stuff
game.hero = null;
Since hero lives inside an object which is stored in game, which is in a global context, If I set for instance hero to null, would this be disposed by the GC?

Global variables are never disposed of by the GC in the sense that a global variable will still exist. Setting it to null will allow the memory that it references to be collected, however.
E.g.
Before:
global -> {nothingness}
After:
global -> var a -> object { foo: "bar" }
Set a to null:
global -> var a -> null
Here, the memory used by the object will be eligible for collection. The variable a still exists though, and it simply references null.
The statement that global variables are never collected is slightly misleading. It might be more accurate to say that any memory that is traceable back to the global context is not currently eligible for collection.
In answer to your question, yes - the hero object will be eligible for collection, because its indirect connection to the global context has been severed.

Related

Is important to set 'var = null' in the end of lexical scope?

I was reading this post that clarified almost everything about scopes, leaving only this doubt:
If lexical scopes generate a new environment on each run and store their information, in an environment where code runs frequently, you need to declare var_of_scope = null at the end of the scope to free memory or JavaScript recognizes this automatically if not are there elements that refer to the environment?
No, that is almost never necessary.
Javascript uses garbage collection. When no values in any scope reference a value stored in memory, it is removed during the next run of garbage collector.
In the situation you describe:
function foo() {
let data = "some data here"
// do stuff with data
data = null
}
Setting the null here is not helpful. It does remove all references the previous value of data, but since the scope will end when the function ends, all local variables will be discarded along with it anyway.
In fact, this would prevent you from using the const keyword, which is a very very good thing to use. All your variables should be const by default, and you should change them to let only if you really need to assign them after initialization.
This is better:
function foo() {
const data = "some data here"
// do stuff with data
}
In general, you just don't have to worry about this. It's not easy to leak memory in javascript like it is in a language like C. It's possible but as long your following most best practices you'll probably be fine.

JavaScript Closures - function scope [duplicate]

This question already has answers here:
How are closures and scopes represented at run time in JavaScript
(2 answers)
About closure, LexicalEnvironment and GC
(3 answers)
Closed 5 years ago.
I have a question related to JavaScript Closures, in specific to the scope when calling a (inner) function.
The question also relates to browser memory leaking as we will see.
At first a "short" introduction to my problem:
So I know when a function is called it enters an execution context (which is added on top of the call stack). There an "Activation object" is created with all the local variables, the function's arguments object and parameters added to it (as properties).
Since inner functions can access variables of enclosing functions - even if the inner function is called after the execution of its enclosing function has ended - there has to be some reference to the "free" (= outer) variables. This is managed by the scope chain which is also added to the execution context.
According to this site, the execution context's scope consists of the actual Activation object at the top of a list which is hiddenly saved on the function itself:
A scope consists of a list (or chain) of objects. Each function object has an internal [[scope]] property [...] The scope that is assigned to the execution context of a function call consists of the list referred to by the [[scope]] property of the corresponding function object with the Activation object added at the front of the chain (or the top of the list).
This is completely logic because due to this internal scope property, references to the free variables exist and so firstly the Closure is able to reach the variables (by going through the scope chain) and secondly it prevents the Garbage Collector from freeing the associated memory when the execution of the enclosing function ends.
In short: the scope chain (including the function's internal scope property) is the reason why Closures work as they do.
So now concretely to my question:
Which variables are added to the function's internal scope property?
As i understand the following part of this MDN article:
A closure is the combination of a function and the lexical environment within which that function was declared. This environment consists of any local variables that were in-scope at the time that the closure was created.
... this would mean that references to all local variables would be added to the internal scope property when forming a Closure.
This seems a bit unnecessary, when the Closure doesn't use all the local variables from its enclosing function, but no matter; the real problem is that this would lead to memory leaks as we will see in the following.
Consider following code (it's a small reduction of this article, to which we will come to later):
var theThing = null;
var replaceThing = function () {
var priorThing = theThing; // hold on to the prior thing
theThing = {
longStr: new Array(1000000).join('*'), // create a 1MB object
someMethod: function () {
console.log("someMessage");
}
};
};
setInterval(replaceThing, 1000); // invoke `replaceThing' once every second
After the first function call of replaceThing following would happen:
priorThing = null
theThing references to a new object (let's say with address 0x01) containing following properties:
a 1MB object
function someMethod whose internal scope property has references to all local variables of the enclosing function, this means also to priorThing which is null
After the second function call:
priorThing = reference to object with address 0x01
theThing references to a new object (let's say with address 0x02) containing following properties:
a 1MB object
function someMethod whose internal scope property has a reference to priorThing (with the address 0x01)
priorThing itself points to a object with the same structure ...
So what's happening?
On each function call a new object is created which references to the object created in the function call before; although we don't even use this object in our new object. It just happens due to the scope chain of the function closure.
So we see saving references to all local variables of the enclosing function is pretty bad.
A better way would be to just save these we really need.
So, from the previous article I conclude that this is really done so and this would solve the memory leak problem I described above.
But furthermore it says following:
But as soon as a variable is used by any closure, it ends up in the lexical environment shared by all closures in that scope.
Well, this would create another possibility to create memory leaks as the author describes in his example - but this would be a programmer's bug.
Okey, so now summed up shortly:
Are all local variables referenced in the closure's scope? (as MDN says)
Would be the worst, because of memory leaks.
Are the variables referenced by all closures if any closure uses it? (as this source says)
Would be the best, because memory leaks are avoided - but bugs could happen, if the programmer isn't aware of this behaviour.
Or does every closure have its own references depending on which variables are used by themselves?
Would completely avoid memory leaks, but a bit more memory would be needed because there has to be a own "lexical environment" object (which is referenced by the internal scope property) for each closure.

In a class constructor why is "this required"? why cant I use local variables?

I know that local variables dosent work when testing it, but I dont understand the concept. Why does "this" work and local variables does not? a clarification would be great on why I must use this and avoid local variables!
code:
function Person(job, married) {
var employ = job;
var status = married;
}
var ray = new Person("student", true);
console.log(ray);
You can use local variables in your constructor, but they don't automatically become instance variables of your object. Instead, the way you are using them, they are just temporal local variables, like local variables inside any function definition.
When you do this:
function Person(job, married) {
var employ = job;
var status = married;
}
var ray = new Person("student", true);
Here's what is happening:
You define a function named Person.
In that function, you define two local variables named employ and status.
Those are normal local variables within a function. They are only visible to code within that function. These may be useful for some things, but they are not available to any code outside that function. They are not available to prototyped methods of your object, they are not available to other code outside that function. In fact, without some sort of reference that creates a closure, they have a limited lifetime and are gone and garbage collected as soon as the Person function finishes executing.
So, if you intended to create the C++ equivalent of member variables of your object, this did not accomplish that. The variables are used only for the duration of the Person() function and are then disposed of and have no lasting presence.
Then, when you execute var ray = new Person("student", true);, the following things happen.
The new causes the system to create a new object, set the value of this to point to that new object and then call the Person constructor with your two arguments.
Your code then creates two local variables which you assign the two arguments to.
The Person() function then finishes executing and the two local variables are disposed of because the scope in which they were defined is done and is garbage collected.
You then assign the newly created object to the variable ray. It is indeed a new object, but it has no custom instance data because nothing was stored in a lasting way.
If you then do console.log(ray), you're just going to see an empty object with no instance data other than what the default Object instance has. Your custom data was not stored anywhere lasting so it's gone now.
If you intend for those two arguments to be saved somewhere lasting as instance data of the object, you have a couple choices. The more traditional choice is to make them publicly accessible properties of the object. You would do that like this:
function Person(job, married) {
this.employ = job;
this.status = married;
}
Since this points to the newly created object, this code assigns the job and married arguments to properties of the newly created object. These properties can be accessed either by other methods on the object or by any code outside of the constructor like this:
var ray = new Person("student", true);
console.log(ray.employ); // "student"
console.log(ray.status); // true
These properties are publicly accessible.
There are some interesting things you can do with those local variables that can allow them to persist and be used after the object is created. To do that, you have to create a closure. I think of a closure as a function scope that would normally be discarded when the function finishes executing, but because of circumstances, there are still live references within the function scope so the garbage collector does not throw away the function scope when the function finishes executing like it would in a purely stack based language like C++. Instead, it persists and can be accessed by code after the object has been created. Here's an example:
function Person(job, married) {
var employ = job;
var status = married;
this.getEmploy = function() {
return employ;
}
this.getStatus = function() {
return status;
}
}
var ray = new Person("student", true);
console.log(ray.getEmploy()); // "student"
console.log(ray.getStatus()); // true
Here's the assignment of functions within the constructor has created a closure. The private local variables employ and status are still private to within the scope of the Person function. But, because the getEmploy and getStatus properties are now publicly exposed and can be called at some time in the future and those functions reference the employ and status variables, the garbage collector realizes that it can't garbage collect the employ and status variables so they persist for the lifetime of this newly created Person object.
Using terms familiar to other object oriented languages like C++, the employ and status local variables are giving you some of the features of private instance variables. Some people call this a hack to fill the void of a feature that Javascript does not offer quite so directly. But, I don't see it as a hack. The language offers closures as an enormously useful feature that can be used in so many ways and this is just one way of using a closure to create a benefit, the benefit of private instance data.
Only the publicly assigned properties getEmploy and getStatus can be accessed by the outside world, but by calling them, we can access the private variables employ and status. If we do console.log(ray) in this new model, we still won't see employ and status there because as far as the console is concerned, they still aren't properties of the ray object. But, because of closures, they are uniquely accessible by the methods on the ray object.
Further, because a new closure is created each time we call the Person constructor, these employ and status variables are uniquely associated with each new instance of the Person object. They behave and work like private members of the object.
For more examples of this type of structure and some more explanation, see this classic discussion: http://javascript.crockford.com/private.html
Why does "this" work and local variables does not?
Unless some sort of lasting closure is created, local variables are temporal. They last only as long as the containing function is executing and they are then garbage collected. Just because they are declared inside a function that you are using as a constructor does not make them special. They are just local variables and have no magic powers beyond just being local variables.
In a class constructor why is “this required”?
a clarification would be great on why I must use this and avoid local
variables!
If you want to assign properties to your object, it is this that points to your object in the constructor so the only way to assign to a property of your object is to reference the object as this.someProperty = xxxx. That's just how the language works. All property references in Javascript require an object as the first part of the access. And, in a constructor, the reference for the newly created object is this. That's how the language was designed.
Those coming from some other object oriented languages might thing you can declare an instance variable of a class and then just use that name all by itself and the interpreter will somehow just know that it's an instance variable name, not a variable name. That might be true in some other languages. That is not true in Javascript. All property references, whether in the constructor, in some method or accessed from the outside as a property on an object must all use an object as the base of the reference. And, inside the constructor and inside a method, that base is the value of this. So, this.someProperty is how you reference that property on the current instance.
Think of it like this:
A class is basically an object, right? Well, when you declare a new instance of Person, you're saying "let's create a new object with properties x, y, and z." Using "this" allows you to access the properties for that instance later, while local variables aren't treated as properties for your object.
When a function is called as a constructor (using the new keyword), a new object is created (the instance object), prototyped on the object value of the function's prototype property, and the constructor called with its this value set to the new instance object just created.
Constructor code can set properties and methods on this (the instance object), which is the return value of the constructor call (... unless the constructor explicitly returns some other object).
If variables defined within the constructor are accessed by nested functions which persist after the contructor returns, they will not be garbage collected because they can still be accessed. If they are not accessible after the constructor returns they are essentially discarded and become available for garbage collection.
Object creation is fundamental to JavaScript behavior: Try looking up and reading about the use of constructor functions.
More about retention of variables in the scope of nested functions after an outer function exits can be found by searching for "closures in JavaScript".

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;

Memory release from local variable in JavaScript

I have a JS function which gets called on the page every few seconds. It's an AJAX update thing.
Being a function, I declare local variables. I don't want to use closures or global variables for various reasons.
I'd never considered this, but do I need to release/clear the variables at the end of the function to release memory or will JS do this for me automatically?
Generally, no. Variables declared with var are local and are garbage collected when you return. If you omit the var then the variables are global, and using the delete keyword may be useful for global variables in some instances, but generally it's good practice to declare all variables with var anyway to not pollute the window namespace.
delete can be useful when using prototype-based inheritence though, e.g:
function myclass() {
this.variable = 'myvalue'
...
delete this.variable // finished with this variable
}
var inst = new myclass()
Bear in mind that if inst is deleted or becomes out of scope (garbage collected) all the attributes in it will be deleted as well. delete can also be useful for deleting items from hash tables:
var d = {}
d['blah'] = 'myvalue'
...
delete d['blah']
There are some browser-specific garbage collection bugs. IE sometimes has problems cleaning attributes in DOM elements and closures etc for example, though many of these problems have been reduced in IE8 I believe.
Javascript has automatic garbage collection. You don't need to deallocate anything.
Variables are released once they are out of scope, in your case, the local variables that are declared inside your function will be automatically freed by js garbage collector, you don't have to worry about them.

Categories

Resources