JavaScript in Plain English: Functions and Closures
Note: This post was originally published on the Quick Left blog on 1/6/16.
Sometimes the world is just more complicated than it needs to be. Let’s quickly break down some common JavaScript stumbling blocks in plain english.
Function Declaration vs. Function Expression
Function Declarations
Function declarations, or function statements, start with the keyword function
.
function boilWater(minutes) {
console.log('Boiling water for ' + minutes + ' minutes');
}
When a JavaScript program is run, all function declarations are stored in memory prior to executing the program. For that reason, you can invoke the boilWater
function before it is even declared.
boilWater(5); //=> 'Boiling water for 5 minutes'function boilWater(minutes) { ... };boilWater(5); //=> 'Boiling water for 5 minutes'
Function Expressions
Function expressions are functions that are stored as variables.
var boilWater = function(minutes) {
console.log('Boiling water for ' + minutes + ' minutes');
}
This time, when the program is run, the variable boilWater
is stored in memory, but the expression is not yet evaluated. Until it is, the value of boilWater
will be the keyword undefined
. After the expression however, we’re free to invoke the expression as intended.
boilWater(10); //=> TypeError: boilWater is not a function...
console.log(boilWater); //=> undefinedvar boilWater = function(minutes) { ... };boilWater(10); //=> 'Boiling water for 10 minutes'
When should I use each?
This is partly a matter of personal style. I subscribe to the school of thought of using function declarations until your situation requires a function expression. While function expressions have the above-mentioned risk, they are also more versatile, allowing you to pass a function on to another part of your program.
First-Class Functions
All that’s implied by the “first-class” title is the ability to create functions on the fly. In JavaScript, a function is just another object with properties and methods, and can be utilized like one.
You may pass them as arguments to other functions;
function forgetfulGreet(fn, milliseconds) {
console.log('Hello again... uh... ');
setTimeout(fn, milliseconds);
};forgetfulGreet(function() { console.log('Marc') }, 2000);//=> 'Hello again... uh...'
//=> 'Marc'
or have a function return another function.
function cardGenerator(suit) {
return function(value) {
console.log(value + ' of ' + suit);
}
}; var spadesGenerator = cardGenerator('Spades');spadesGenerator('Four'); //=> 'Four of Spades'
Closures
Conveniently, we just used one in the last example. Closures are not something you, the developer, can write. They are a feature of the JavaScript language that you can leverage, and probably already have without knowing it.
When you create a function inside of another function, JavaScript preserves whatever variables that nested function may need in a closure. In the previous example, when we invoke spadesGenerator
, the variable suit
is spared from garbage collection and available to us, thanks to a closure.
Typically when a function executes, its context is preserved for the duration of that execution, then it is gone — removed from the stack. In the case of closures, the inner function maintains a reference to the context of its parent function, even after that parent function has come and gone from the stack.
Now What?
Hopefully this clears up some big-picture questions. We’ve glossed over some nuances in an effort to get to the heart of these concepts. If you’re interested in exploring these topics in more depth, start by reading MDN’s function references. You’ll find great elaborations on function expressions, function declarations and closures. Alternatively, ask your question below or let me know what other JavaScript topics you’d like to read in plain english.