Should I encapsulate blocks of functionality in anonymous JavaScript functions? - javascript

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.

Related

JavaScript experts: Do block-scopes with `{}` and anonymous functions both help garbage-collection?

In the book "You don't know JS: scopes & closures", Kyle simpson states that a block-scoped variable helps with garbage collection, here is the specific example:
function process(data) {
// do something interesting
}
{
let someReallyBigData = {};
process(someReallyBigData);
}
var btn = document.getElementById("my_button");
btn.addEventListener("click", function click(evt) {
console.log("Clicked!");
}, false);
Now the above example is supposed to help with garbage-collection since the variable someReallyBigData will be dropped from memory as soon as the block ends, unlike this example, which doesn't help with garbage-collection:
function process(data) {
// do something interesting
}
var someReallyBigData = {};
process(someReallyBigData);
var btn = document.getElementById("my_button");
btn.addEventListener("click", function click(evt) {
console.log("Clicked!");
}, false);
Now I am sure this guy is correct about the examples he provided (the first one); however, i am wondering whether or not everything would be the same if we used an anonymous IIFE (Immediately Invoked Function Expression) along with a normal var instead of the {} curly braces and the let variable. Let me turn that into an example:
function process(data) {
// do something interesting
}
(function(){
var someReallyBigData = {};
process(someReallyBigData);
}());
var btn = document.getElementById("my_button");
btn.addEventListener("click", function click(evt) {
console.log("Clicked!");
}, false);
Looking at it from the surface, they both should do the same thing; since just as the block-scoped someReallyBigData variable could not be accessed anymore by anything after the block of code had executed, the code inside the anonymous function cannot be accessed by anything once it has executed, by anything, from anywhere.
So, do they really have the same effect on the garbage-collection mechanisms of the Javascript engine ? I was almost certain this was the case until I googled "anonymous function garbage-collection" and almost all the material that showed up said only negative things like "anonymous functions cause memory leaks" and etc.
I would be glad if someone could shed some light on this thing.
Please don't forget that my question is a bit specific to the examples I provided, thanks!
(V8 developer here.) Yes, there are several ways to make objects unreachable, including at least all of the following:
Put stuff in let-declared variables in a block scope
Put stuff into an IIFE
Clear the variable (var or let) when you're done with it: someReallyBigData = null;
The end result will be the same in all cases: objects that are no longer reachable are eligible for garbage collection.
Other notes based on the discussion here:
The advice quoted in the question makes sense for top-level code. Within a reasonably sized function, I wouldn't worry about it -- the function will probably return soon enough that there is no difference, so you don't need to burden yourself with such considerations.
There's a big difference between "an object can be freed now" and "an object will be freed now". Letting something go out of scope does not cause it to be freed immediately, and does not cause the garbage collector to run more often. It just means that whenever the garbage collector next decides to go looking for garbage, the object in question will be eligible.
IIFEs are IIFEs regardless of whether they're anonymous or not. Example:
(function I_have_a_name() {
var someReallyBigData = ...;
})();
// someReallyBigData can be collected now.
I_have_a_name(); // ReferenceError: I_have_a_name is not defined
Creating closures in and of itself does not keep things alive. However, if closures reference variables in their outer scope, then (of course!) those can't be collected as long as the closure is around. Example:
var closure = (function() {
var big_data_1 = ...;
var big_data_2 = ...;
return function() { return big_data_1.foo; }
})();
// big_data_2 can be collected at this point.
closure(); // This needs big_data_1.
// big_data_1 still cannot be collected, closure might need it again.
closure = null;
// big_data_1 can be collected now.
The optimizing compiler has little influence on all this. It usually operates on a per-function bases, and usually the top-level is not optimized (because most logic tends to be in functions). Within a function, the optimizing compiler is very well aware of the lifetimes of objects (that's part of what it means to be an optimizing compiler).
JavaScript only has block level scope when you use the let or const keywords in declarations. Just because you have {} alone does not create block-level scope (as is the case in most other languages).
Aside from that, garbage collection is implementation dependent and you would most likely not notice any difference in performance due to block scoping.
Anonymous functions can have an impact on garbage collection because the function can be set up in such a way that it doesn't have to be stored for potential calling later. A good example of this would be a function that needs to run only once (i.e. when the document is fully parsed):
window.addEventListener("DOMContentLoaded", function(){ . . . });
However, that doesn't mean that all anonymous functions provide this benefit because the function could wind up being stored (i.e. if it is returned from a function and then captured in a variable) or if the anonymous function sets up closures, then all bets are off.
Also, be aware that you can't unit test anonymous functions as simply as you can named functions.
I am wondering whether or not everything would be the same if we used an anonymous IIFE
Sure that's possible, it's what transpilers do to emulate block scopes as well. However IIFEs look a bit awkward, block scopes with let/const variables are easier to use. See also Will const and let make the IIFE pattern unnecessary?.
Now the first example is supposed to help with garbage-collection since the variable someReallyBigData will be dropped from memory as soon as the block ends, unlike the second example, which doesn't help with garbage-collection.
Notice that the word is helps, not enables. Today's engines can garbage-collect the variable just fine, as their optimiser sees that it's not used in the preserved closure. The block scope only makes this kind of static analysis easier.

Should I put my entire Javasscript script inside a self invoking function? [duplicate]

In javascript, when would you want to use this:
(function(){
//Bunch of code...
})();
over this:
//Bunch of code...
It's all about variable scoping. Variables declared in the self executing function are, by default, only available to code within the self executing function. This allows code to be written without concern of how variables are named in other blocks of JavaScript code.
For example, as mentioned in a comment by Alexander:
(function() {
var foo = 3;
console.log(foo);
})();
console.log(foo);
This will first log 3 and then throw an error on the next console.log because foo is not defined.
Simplistic. So very normal looking, its almost comforting:
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
However, what if I include a really handy javascript library to my page that translates advanced characters into their base level representations?
Wait... what?
I mean, if someone types in a character with some kind of accent on it, but I only want 'English' characters A-Z in my program? Well... the Spanish 'ñ' and French 'é' characters can be translated into base characters of 'n' and 'e'.
So someone nice person has written a comprehensive character converter out there that I can include in my site... I include it.
One problem: it has a function in it called 'name' same as my function.
This is what's called a collision. We've got two functions declared in the same scope with the same name. We want to avoid this.
So we need to scope our code somehow.
The only way to scope code in javascript is to wrap it in a function:
function main() {
// We are now in our own sound-proofed room and the
// character-converter library's name() function can exist at the
// same time as ours.
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
That might solve our problem. Everything is now enclosed and can only be accessed from within our opening and closing braces.
We have a function in a function... which is weird to look at, but totally legal.
Only one problem. Our code doesn't work.
Our userName variable is never echoed into the console!
We can solve this issue by adding a call to our function after our existing code block...
function main() {
// We are now in our own sound-proofed room and the
// character-converter libarary's name() function can exist at the
// same time as ours.
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
main();
Or before!
main();
function main() {
// We are now in our own sound-proofed room and the
// character-converter libarary's name() function can exist at the
// same time as ours.
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
A secondary concern: What are the chances that the name 'main' hasn't been used yet? ...so very, very slim.
We need MORE scoping. And some way to automatically execute our main() function.
Now we come to auto-execution functions (or self-executing, self-running, whatever).
((){})();
The syntax is awkward as sin. However, it works.
When you wrap a function definition in parentheses, and include a parameter list (another set or parentheses!) it acts as a function call.
So lets look at our code again, with some self-executing syntax:
(function main() {
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
)();
So, in most tutorials you read, you will now be bombarded with the term 'anonymous self-executing' or something similar.
After many years of professional development, I strongly urge you to name every function you write for debugging purposes.
When something goes wrong (and it will), you will be checking the backtrace in your browser. It is always easier to narrow your code issues when the entries in the stack trace have names!
Self-invocation (also known as
auto-invocation) is when a function
executes immediately upon its
definition. This is a core pattern and
serves as the foundation for many
other patterns of JavaScript
development.
I am a great fan :) of it because:
It keeps code to a minimum
It enforces separation of behavior from presentation
It provides a closure which prevents naming conflicts
Enormously – (Why you should say its good?)
It’s about defining and executing a function all at once.
You could have that self-executing function return a value and pass the function as a param to another function.
It’s good for encapsulation.
It’s also good for block scoping.
Yeah, you can enclose all your .js files in a self-executing function and can prevent global namespace pollution. ;)
More here.
Namespacing. JavaScript's scopes are function-level.
I can't believe none of the answers mention implied globals.
The (function(){})() construct does not protect against implied globals, which to me is the bigger concern, see http://yuiblog.com/blog/2006/06/01/global-domination/
Basically the function block makes sure all the dependent "global vars" you defined are confined to your program, it does not protect you against defining implicit globals. JSHint or the like can provide recommendations on how to defend against this behavior.
The more concise var App = {} syntax provides a similar level of protection, and may be wrapped in the function block when on 'public' pages. (see Ember.js or SproutCore for real world examples of libraries that use this construct)
As far as private properties go, they are kind of overrated unless you are creating a public framework or library, but if you need to implement them, Douglas Crockford has some good ideas.
I've read all answers, something very important is missing here, I'll KISS. There are 2 main reasons, why I need Self-Executing Anonymous Functions, or better said "Immediately-Invoked Function Expression (IIFE)":
Better namespace management (Avoiding Namespace Pollution -> JS Module)
Closures (Simulating Private Class Members, as known from OOP)
The first one has been explained very well. For the second one, please study following example:
var MyClosureObject = (function (){
var MyName = 'Michael Jackson RIP';
return {
getMyName: function () { return MyName;},
setMyName: function (name) { MyName = name}
}
}());
Attention 1: We are not assigning a function to MyClosureObject, further more the result of invoking that function. Be aware of () in the last line.
Attention 2: What do you additionally have to know about functions in Javascript is that the inner functions get access to the parameters and variables of the functions, they are defined within.
Let us try some experiments:
I can get MyName using getMyName and it works:
console.log(MyClosureObject.getMyName());
// Michael Jackson RIP
The following ingenuous approach would not work:
console.log(MyClosureObject.MyName);
// undefined
But I can set an another name and get the expected result:
MyClosureObject.setMyName('George Michael RIP');
console.log(MyClosureObject.getMyName());
// George Michael RIP
Edit: In the example above MyClosureObject is designed to be used without the newprefix, therefore by convention it should not be capitalized.
Scope isolation, maybe. So that the variables inside the function declaration don't pollute the outer namespace.
Of course, on half the JS implementations out there, they will anyway.
Is there a parameter and the "Bunch of code" returns a function?
var a = function(x) { return function() { document.write(x); } }(something);
Closure. The value of something gets used by the function assigned to a. something could have some varying value (for loop) and every time a has a new function.
Here's a solid example of how a self invoking anonymous function could be useful.
for( var i = 0; i < 10; i++ ) {
setTimeout(function(){
console.log(i)
})
}
Output: 10, 10, 10, 10, 10...
for( var i = 0; i < 10; i++ ) {
(function(num){
setTimeout(function(){
console.log(num)
})
})(i)
}
Output: 0, 1, 2, 3, 4...
Short answer is : to prevent pollution of the Global (or higher) scope.
IIFE (Immediately Invoked Function Expressions) is the best practice for writing scripts as plug-ins, add-ons, user scripts or whatever scripts are expected to work with other people's scripts. This ensures that any variable you define does not give undesired effects on other scripts.
This is the other way to write IIFE expression. I personally prefer this following method:
void function() {
console.log('boo!');
// expected output: "boo!"
}();
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/void
From the example above it is very clear that IIFE can also affect efficiency and performance, because the function that is expected to be run only once will be executed once and then dumped into the void for good. This means that function or method declaration does not remain in memory.
One difference is that the variables that you declare in the function are local, so they go away when you exit the function and they don't conflict with other variables in other or same code.
First you must visit MDN IIFE , Now some points about this
this is Immediately Invoked Function Expression. So when your javascript file invoked from HTML this function called immediately.
This prevents accessing variables within the IIFE idiom as well as polluting the global scope.
Self executing function are used to manage the scope of a Variable.
The scope of a variable is the region of your program in which it is defined.
A global variable has global scope; it is defined everywhere in your JavaScript code and can be accessed from anywhere within the script, even in your functions. On the other hand, variables declared within a function are defined only within the body of the function.
They are local variables, have local scope and can only be accessed within that function. Function parameters also count as local variables and are defined only within the body of the function.
As shown below, you can access the global variables variable inside your function and also note that within the body of a function, a local variable takes precedence over a global variable with the same name.
var globalvar = "globalvar"; // this var can be accessed anywhere within the script
function scope() {
alert(globalvar);
var localvar = "localvar"; //can only be accessed within the function scope
}
scope();
So basically a self executing function allows code to be written without concern of how variables are named in other blocks of javascript code.
Since functions in Javascript are first-class object, by defining it that way, it effectively defines a "class" much like C++ or C#.
That function can define local variables, and have functions within it. The internal functions (effectively instance methods) will have access to the local variables (effectively instance variables), but they will be isolated from the rest of the script.
Self invoked function in javascript:
A self-invoking expression is invoked (started) automatically, without being called. A self-invoking expression is invoked right after its created. This is basically used for avoiding naming conflict as well as for achieving encapsulation. The variables or declared objects are not accessible outside this function. For avoiding the problems of minimization(filename.min) always use self executed function.
(function(){
var foo = {
name: 'bob'
};
console.log(foo.name); // bob
})();
console.log(foo.name); // Reference error
Actually, the above function will be treated as function expression without a name.
The main purpose of wrapping a function with close and open parenthesis is to avoid polluting the global space.
The variables and functions inside the function expression became private (i.e) they will not be available outside of the function.
Given your simple question: "In javascript, when would you want to use this:..."
I like #ken_browning and #sean_holding's answers, but here's another use-case that I don't see mentioned:
let red_tree = new Node(10);
(async function () {
for (let i = 0; i < 1000; i++) {
await red_tree.insert(i);
}
})();
console.log('----->red_tree.printInOrder():', red_tree.printInOrder());
where Node.insert is some asynchronous action.
I can't just call await without the async keyword at the declaration of my function, and i don't need a named function for later use, but need to await that insert call or i need some other richer features (who knows?).
It looks like this question has been answered all ready, but I'll post my input anyway.
I know when I like to use self-executing functions.
var myObject = {
childObject: new function(){
// bunch of code
},
objVar1: <value>,
objVar2: <value>
}
The function allows me to use some extra code to define the childObjects attributes and properties for cleaner code, such as setting commonly used variables or executing mathematic equations; Oh! or error checking. as opposed to being limited to nested object instantiation syntax of...
object: {
childObject: {
childObject: {<value>, <value>, <value>}
},
objVar1: <value>,
objVar2: <value>
}
Coding in general has a lot of obscure ways of doing a lot of the same things, making you wonder, "Why bother?" But new situations keep popping up where you can no longer rely on basic/core principals alone.
You can use this function to return values :
var Test = (function (){
const alternative = function(){ return 'Error Get Function '},
methods = {
GetName: alternative,
GetAge:alternative
}
// If the condition is not met, the default text will be returned
// replace to 55 < 44
if( 55 > 44){
// Function one
methods.GetName = function (name) {
return name;
};
// Function Two
methods.GetAge = function (age) {
return age;
};
}
return methods;
}());
// Call
console.log( Test.GetName("Yehia") );
console.log( Test.GetAge(66) );
Use of this methodology is for closures. Read this link for more about closures.
IIRC it allows you to create private properties and methods.

Javascript Function Declaration Options

I've seen experts using below to declare a function:
(function () {
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
//etc
}());
e.g.
https://github.com/douglascrockford/JSON-js/blob/master/json.js
Could someone help me understand when should we use above pattern and how do we make use of it?
Thanks.
Well, since ECMA6 hasn't arrived yet, functions are about the best way to create scopes in JS. If you wrap a variable declaration of sorts in an IIFE (Immediately Invoked Function Expression), that variable will not be created globally. Same goes for function declarations.
If you're given the seemingly daunting task of clearing a script of all global variables, all you need to do is wrap the entire script in a simple (function(){/*script here*/}());, and no globals are created, lest they are implied globals, but that's just a lazy fix. This pattern is sooo much more powerful.
I have explained the use of IIFE in more detail both here, here and here
The basic JS function call live-cycle sort of works like this:
f();//call function
||
====> inside function, some vars are created, along with the arguments object
These reside in an internal scope object
==> function returns, scope object (all vars and args) are GC'ed
Like all objects in JS, an object is flagged for GC (Garbage Collection) as soon as that object is not referenced anymore. But consider the following:
var foo = (function()
{
var localFoo = {bar:undefined};
return function(get, set)
{
if (set === undefined)
{
return localFoo[get];
}
return (localFoo[get] = set);
}
}());
When the IIFE returns, foo is assigned its return value, which is another function. Now localFoo was declared in the scope of the IIFE, and there is no way to get to that object directly. At first glance you might expect localFoo to be GC'ed.
But hold on, the function that is being returned (and assigned to foo still references that object, so it can't be gc'ed. In other words: the scope object outlives the function call, and a closure is created.
The localFoo object, then, will not be GC'ed until the variable foo either goes out of scope or is reassigned another value and all references to the returned function are lost.
Take a look at one of the linked answers (the one with the diagrams), In that answer there's a link to an article, from where I stole the images I used. That should clear things up for you, if this hasn't already.
An IIFE can return nothing, but expose its scope regardless:
var foo = {};
(function(obj)
{
//obj references foo here
var localFoo = {};
obj.property = 'I am set in a different scope';
obj.getLocal = function()
{
return localFoo;
};
}(foo));
This IIFE returns nothing (implied undefined), yet console.log(foo.getLocal()) will log the empty object literal. foo itself will also be assigned property. But wait, I can do you one better. Assume foo has been passed through the code above once over:
var bar = foo.getLocal();
bar.newProperty = 'I was added using the bar reference';
bar.getLocal = function()
{
return this;
};
console.log(foo.getLocal().newProperty === bar.newProperty);
console.log(bar ==== foo.getLocal());
console.log(bar.getLocal() === foo.getLocal().getLocal());
//and so on
What will this log? Indeed, it'll log true time and time again. Objects are never copied in JS, their references are copied, but the object is always the same. Change it once in some scope, and those changes will be shared across all references (logically).
This is just to show you that closures can be difficult to get your head round at first, but this also shows how powerful they can be: you can pass an object through various IIFE's, each time setting a new method that has access to its own, unique scope that other methdods can't get to.
Note
Closers aren't all that easy for the JS engines to Garbage Collect, but lately, that's not that big of an issue anymore.
Also take your time to google these terms:
the module pattern in JavaScript Some reasons WHY we use it
closures in JavaScript Second hit
JavaScript function scope First hit
JavaScript function context The dreaded this reference
IIFE's can be named functions, too, but then the only place where you can reference that function is inside that function's scope:
(function init (obj)
{
//obj references foo here
var localFoo = {};
obj.property = 'I am set in a different scope';
obj.getLocal = function()
{
return localFoo;
};
if (!this.wrap)
{//only assign wrap if wrap/init wasn't called from a wrapped object (IE foo)
obj.wrap = init;
}
}(foo));
var fooLocal = foo.getLocal();
//assign all but factory methods to fooLocal:
foo.wrap(fooLocal);
console.log(fooLocal.getLocal());//circular reference, though
console.log(init);//undefined, the function name is not global, because it's an expression
This is just a basic example of how you can usre closures to create wrapper objects...
Well the above pattern is called the immediate function. This function do 3 things:-
The result of this code is an expression that does all of the following in a single statement:
Creates a function instance
Executes the function
Discards the function (as there are no longer any references to it after the statement
has ended)
This is used by the JS developers for creating a variables and functions without polluting the global space as it creates it's own private scope for vars and functions.
In the above example the function f(){} is in the private scope of the immediate function, you can't invoke this function at global or window scope.
Browser-based JavaScript only has two scopes available: Global and Function. This means that any variables you create are in the global scope or confined to the scope of the function that you are currently in.
Sometimes, often during initialization, you need a bunch of variables that you only need once. Putting them in the global scope isn't appropriate bit you don't want a special function to do it.
Enter, the immediate function. This is a function that is defined and then immediately called. That's what you are seeing in Crockford's (and others') code. It can be anonymous or named, without defeating the purpose of avoiding polluting the global scope because the name of the function will be local to the function body.
It provides a scope for containing your variables without leaving a function lying around. Keeps things clean.

javascript closure advantages?

Whats the main purpose of Closures in JS. Is it just used for public and private variables? or is there something else that I missed. I am trying to understand closure and really want to know what are the main advantages of using it.
Closures have to do with how javascript is scoped. To say it another way, because of the scoping choices (i.e. lexical scoping) the javascript designers made, closures are possible.
The advantage of closures in javascript is that it allows you to bind a variable to an execution context.
var closedIn = {};
var f = function(){
closedIn.blah = 'blah'; // closedIn was just "closed in" because I used in the function, but it was defined outside the function.
}
in that example, you have a normal object literal called closedIn. It is accessed in a function. Because of that, javascript knows it has to bring closedIn everywhere it brings the function f, so it is available to f.
The this keyword is tricky. this is always a reference to the execution scope. You can capture the this of one context to use in another context as follows:
var that = this;
var f = function(){
that.somethingOnThat();
// `this` means the scope f, `that` means whatever 'this' was when defined outside of the function
}
This trick can be very useful somethings, if you are coding object oriented javascript and want a callback to have access to some external scope.
To quote from a Javascript book:
"Functions in JavaScript are lexically
rather than dynamically scoped. This
means that they run in the scope in
which they are defined, not the scopee
from which they are executed. When a
function is defined, the current scope
chain is saved and becomes part of the
internal state of the function."
So the clear advantage is that you can bring any object (functions, objects, etc) along with the scope chain as far as is necessary. This is can also be considered a risk, because your apps can easily consume lots of memory if you are not careful.
I think the best phrase to sum up the purpose of closures would be:
Data Encapsulation
With a function closure you can store data in a separate scope, and share it only where necessary.
If you wanted to emulate private static variables, you could define a class inside a function, and define the private static vars within the closure:
(function () {
var foo;
foo = 0;
function MyClass() {
foo += 1;
}
MyClass.prototype = {
howMany: function () {
return foo;
}
};
window.MyClass = MyClass;
}());
Closures are necessary in javascript due to the fact that most API's that require callback functions (for instance, an "onclick" function) do not provide other mechanisms to send parameters to those callback functions (or to explicitly set the "this" pointer). Instead, you need to use closures to allow the callback to access variables in the "parent" function.
I personally wish that they weren't necessary, since they can be hard to understand, make for hard to read code (it's not always clear what exactly is in scope), and make for weird bugs. Instead I wish there was a standard for callbacks that allowed you to send parameters, etc. But I accept that I am in the minority in this view.
As we know, the variables that are defined in functions, have local scope. We can't access them from outside of the function.
Problem 1:
local variables are created when the function is called and they will be destroyed when the function's task is finished. It means local variables have shorter life time than global variables. We may use global variables to overcome that issue.
Global variables are available when the program starts and are destroyed when it ends. They are also available throughout the program.
Problem 2:
Since global variables are accessible throughout the program, they are prone to change from everywhere.
What do we want?
We want to have data persistency + data encapsulation.
We can achieve them by using Closures. By using a closure we can have private variables that are available even after a function's task is finished.
Example:
function initCounter() {
let counter = 0;
return function () {
return ++counter;
}
}
// Each counter is persistent
const countJumps = initCounter();
countJumps();
countJumps();
alert("Jumps count is: " + countJumps());
const countClicks = initCounter();
countClicks();
countClicks();
countClicks();
countClicks();
alert("Clicks count is: " + countClicks());
// Each counter is isolated
alert(counter); // Error: counter is not defined

garbage collection with node.js

I was curious about how the node.js pattern of nested functions works with the garbage collector of v8.
here's a simple example
readfile("blah", function(str) {
var val = getvaluefromstr(str);
function restofprogram(val2) { ... } (val)
})
if restofprogram is long-running, doesn't that mean that str will never get garbage collected? My understanding is that with node you end up with nested functions a lot. Does this get garbage collected if restofprogram was declared outside, so str could not be in scope? Is this a recommended practice?
EDIT I didn't intend to make the problem complicated. That was just carelessness, so I've modified it.
Simple answer: if value of the str is not referenced from anywhere else (and str itself is not referenced from restofprogram) it will become unreachable as soon as the function (str) { ... } returns.
Details: V8 compiler distinguishes real local variables from so called context variables captured by a closure, shadowed by a with-statement or an eval invocation.
Local variables live on the stack and disappear as soon as function execution completes.
Context variables live in a heap allocated context structure. They disappear when the context structure dies. Important thing to note here is that context variables from the same scope live in the same structure. Let me illustrate it with an example code:
function outer () {
var x; // real local variable
var y; // context variable, referenced by inner1
var z; // context variable, referenced by inner2
function inner1 () {
// references context
use(y);
}
function inner2 () {
// references context
use(z);
}
function inner3 () { /* I am empty but I still capture context implicitly */ }
return [inner1, inner2, inner3];
}
In this example variable x will disappear as soon as outer returns but variables y and z will disappear only when both inner1, inner2 and inner3 die. This happens because y and z are allocated in the same context structure and all three closures implicitly reference this context structure (even inner3 which does not use it explicitly).
Situation gets even more complicated when you start using with-statement, try/catch-statement which on V8 contains an implicit with-statement inside catch clause or global eval.
function complication () {
var x; // context variable
function inner () { /* I am empty but I still capture context implicitly */ }
try { } catch (e) { /* contains implicit with-statement */ }
return inner;
}
In this example x will disappear only when inner dies. Because:
try/catch-contains implicit with-statement in catch clause
V8 assumes that any with-statement shadows all the locals
This forces x to become a context variable and inner captures the context so x exists until inner dies.
In general if you want to be sure that given variable does not retain some object for longer than really needed you can easily destroy this link by assigning null to that variable.
Actually your example is somewhat tricky. Was it on purpose? You seem to be masking the outer val variable with an inner lexically scoped restofprogram()'s val argument, instead of actually using it. But anyway, you're asking about str so let me ignore the trickiness of val in your example just for the sake of simplicity.
My guess would be that the str variable won't get collected before the restofprogram() function finishes, even if it doesn't use it. If the restofprogram() doesn't use str and it doesn't use eval() and new Function() then it could be safely collected but I doubt it would. This would be a tricky optimization for V8 probably not worth the trouble. If there was no eval and new Function() in the language then it would be much easier.
Now, it doesn't have to mean that it would never get collected because any event handler in a single-threaded event loop should finish almost instantly. Otherwise your whole process would be blocked and you'd have bigger problems than one useless variable in memory.
Now I wonder if you didn't mean something else than what you actually wrote in your example. The whole program in Node is just like in the browser – it just registers event callbacks that are fired asynchronously later after the main program body has already finished. Also none of the handlers are blocking so no function is actually taking any noticeable time to finish. I'm not sure if I understood what you actually meant in your question but I hope that what I've written will be helpful to understand how it all works.
Update:
After reading more info in the comments on how your program looks like I can say more.
If your program is something like:
readfile("blah", function (str) {
var val = getvaluefromstr(str);
// do something with val
Server.start(function (request) {
// do something
});
});
Then you can also write it like this:
readfile("blah", function (str) {
var val = getvaluefromstr(str);
// do something with val
Server.start(serverCallback);
});
function serverCallback(request) {
// do something
});
It will make the str go out of scope after Server.start() is called and will eventually get collected. Also, it will make your indentation more manageable which is not to be underestimated for more complex programs.
As for the val you might make it a global variable in this case which would greatly simplify your code. Of course you don't have to, you can wrestle with closures, but in this case making val global or making it live in an outer scope common for both the readfile callback and for the serverCallback function seems like the most straightforward solution.
Remember that everywhere when you can use an anonymous function you can also use a named function, and with those you can choose in which scope do you want them to live.
My guess is that str will NOT be garbage collected because it can be used by restofprogram().
Yes, and str should get GCed if restofprogram was declared outside, except, if you do something like this:
function restofprogram(val) { ... }
readfile("blah", function(str) {
var val = getvaluefromstr(str);
restofprogram(val, str);
});
Or if getvaluefromstr is declared as something like this:
function getvaluefromstr(str) {
return {
orig: str,
some_funky_stuff: 23
};
}
Follow-up-question: Does v8 do just plain'ol GC or does it do a combination of GC and ref. counting (like python?)

Categories

Resources