Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 202
Justin Force Avatar asked Sep 20 '10 16:09

Justin Force


People also ask

Why are anonymous functions bad?

1) Anonymous functions cannot be reused. 2) Anonymous functions, by definition, do not have a name and so do not describe what they do. Which is to say the code is not self documenting. 3) Anonymous functions cannot be tested in isolation with a unit testing framework.

How do you encapsulate a function in JavaScript?

Encapsulation means information hiding. It's about hiding as much as possible of the object's internal parts and exposing a minimal public interface. The simplest and most elegant way to create encapsulation in JavaScript is using closures. A closure can be created as a function with private state.

What are the important properties of an anonymous function in JavaScript?

An anonymous function is not accessible after its initial creation, it can only be accessed by a variable it is stored in as a function as a value. An anonymous function can also have multiple arguments, but only one expression.

Are closures the same as anonymous functions?

Anonymous functions, also known as closures , allow the creation of functions which have no specified name. They are most useful as the value of callable parameters, but they have many other uses. Anonymous functions are implemented using the Closure class.


2 Answers

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:

  1. As long as an object is around, none of its slots will be magically freed without your say-so.
  2. 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.

like image 140
Chuck Avatar answered Oct 21 '22 00:10

Chuck


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.

like image 39
Guffa Avatar answered Oct 21 '22 00:10

Guffa