Functions As Values

So far, we’ve discussed functions as the primary mechanism of scope in JavaScript. You recall typical function declaration syntax as follows:

  1. function foo() {
  2. // ..
  3. }

Though it may not seem obvious from that syntax, foo is basically just a variable in the outer enclosing scope that’s given a reference to the function being declared. That is, the function itself is a value, just like 42 or [1,2,3] would be.

This may sound like a strange concept at first, so take a moment to ponder it. Not only can you pass a value (argument) to a function, but a function itself can be a value that’s assigned to variables, or passed to or returned from other functions.

As such, a function value should be thought of as an expression, much like any other value or expression.

Consider:

  1. var foo = function() {
  2. // ..
  3. };
  4. var x = function bar(){
  5. // ..
  6. };

The first function expression assigned to the foo variable is called anonymous because it has no name.

The second function expression is named (bar), even as a reference to it is also assigned to the x variable. Named function expressions are generally more preferable, though anonymous function expressions are still extremely common.

For more information, see the Scope & Closures title of this series.

Immediately Invoked Function Expressions (IIFEs)

In the previous snippet, neither of the function expressions are executed — we could if we had included foo() or x(), for instance.

There’s another way to execute a function expression, which is typically referred to as an immediately invoked function expression (IIFE):

  1. (function IIFE(){
  2. console.log( "Hello!" );
  3. })();
  4. // "Hello!"

The outer ( .. ) that surrounds the (function IIFE(){ .. }) function expression is just a nuance of JS grammar needed to prevent it from being treated as a normal function declaration.

The final () on the end of the expression — the })(); line — is what actually executes the function expression referenced immediately before it.

That may seem strange, but it’s not as foreign as first glance. Consider the similarities between foo and IIFE here:

  1. function foo() { .. }
  2. // `foo` function reference expression,
  3. // then `()` executes it
  4. foo();
  5. // `IIFE` function expression,
  6. // then `()` executes it
  7. (function IIFE(){ .. })();

As you can see, listing the (function IIFE(){ .. }) before its executing () is essentially the same as including foo before its executing (); in both cases, the function reference is executed with () immediately after it.

Because an IIFE is just a function, and functions create variable scope, using an IIFE in this fashion is often used to declare variables that won’t affect the surrounding code outside the IIFE:

  1. var a = 42;
  2. (function IIFE(){
  3. var a = 10;
  4. console.log( a ); // 10
  5. })();
  6. console.log( a ); // 42

IIFEs can also have return values:

  1. var x = (function IIFE(){
  2. return 42;
  3. })();
  4. x; // 42

The 42 value gets returned from the IIFE-named function being executed, and is then assigned to x.

Closure

Closure is one of the most important, and often least understood, concepts in JavaScript. I won’t cover it in deep detail here, and instead refer you to the Scope & Closures title of this series. But I want to say a few things about it so you understand the general concept. It will be one of the most important techniques in your JS skillset.

You can think of closure as a way to “remember” and continue to access a function’s scope (its variables) even once the function has finished running.

Consider:

  1. function makeAdder(x) {
  2. // parameter `x` is an inner variable
  3. // inner function `add()` uses `x`, so
  4. // it has a "closure" over it
  5. function add(y) {
  6. return y + x;
  7. };
  8. return add;
  9. }

The reference to the inner add(..) function that gets returned with each call to the outer makeAdder(..) is able to remember whatever x value was passed in to makeAdder(..). Now, let’s use makeAdder(..):

  1. // `plusOne` gets a reference to the inner `add(..)`
  2. // function with closure over the `x` parameter of
  3. // the outer `makeAdder(..)`
  4. var plusOne = makeAdder( 1 );
  5. // `plusTen` gets a reference to the inner `add(..)`
  6. // function with closure over the `x` parameter of
  7. // the outer `makeAdder(..)`
  8. var plusTen = makeAdder( 10 );
  9. plusOne( 3 ); // 4 <-- 1 + 3
  10. plusOne( 41 ); // 42 <-- 1 + 41
  11. plusTen( 13 ); // 23 <-- 10 + 13

More on how this code works:

  1. When we call makeAdder(1), we get back a reference to its inner add(..) that remembers x as 1. We call this function reference plusOne(..).
  2. When we call makeAdder(10), we get back another reference to its inner add(..) that remembers x as 10. We call this function reference plusTen(..).
  3. When we call plusOne(3), it adds 3 (its inner y) to the 1 (remembered by x), and we get 4 as the result.
  4. When we call plusTen(13), it adds 13 (its inner y) to the 10 (remembered by x), and we get 23 as the result.

Don’t worry if this seems strange and confusing at first — it can be! It’ll take lots of practice to understand it fully.

But trust me, once you do, it’s one of the most powerful and useful techniques in all of programming. It’s definitely worth the effort to let your brain simmer on closures for a bit. In the next section, we’ll get a little more practice with closure.

Modules

The most common usage of closure in JavaScript is the module pattern. Modules let you define private implementation details (variables, functions) that are hidden from the outside world, as well as a public API that is accessible from the outside.

Consider:

  1. function User(){
  2. var username, password;
  3. function doLogin(user,pw) {
  4. username = user;
  5. password = pw;
  6. // do the rest of the login work
  7. }
  8. var publicAPI = {
  9. login: doLogin
  10. };
  11. return publicAPI;
  12. }
  13. // create a `User` module instance
  14. var fred = User();
  15. fred.login( "fred", "12Battery34!" );

The User() function serves as an outer scope that holds the variables username and password, as well as the inner doLogin() function; these are all private inner details of this User module that cannot be accessed from the outside world.

Warning: We are not calling new User() here, on purpose, despite the fact that probably seems more common to most readers. User() is just a function, not a class to be instantiated, so it’s just called normally. Using new would be inappropriate and actually waste resources.

Executing User() creates an instance of the User module — a whole new scope is created, and thus a whole new copy of each of these inner variables/functions. We assign this instance to fred. If we run User() again, we’d get a new instance entirely separate from fred.

The inner doLogin() function has a closure over username and password, meaning it will retain its access to them even after the User() function finishes running.

publicAPI is an object with one property/method on it, login, which is a reference to the inner doLogin() function. When we return publicAPI from User(), it becomes the instance we call fred.

At this point, the outer User() function has finished executing. Normally, you’d think the inner variables like username and password have gone away. But here they have not, because there’s a closure in the login() function keeping them alive.

That’s why we can call fred.login(..) — the same as calling the inner doLogin(..) — and it can still access username and password inner variables.

There’s a good chance that with just this brief glimpse at closure and the module pattern, some of it is still a bit confusing. That’s OK! It takes some work to wrap your brain around it.

From here, go read the Scope & Closures title of this series for a much more in-depth exploration.