Intro to JS Closures

Scope

  • Lexical Scoping
    • ​"functions are executed using the variable scope that was in effect when they were defined, not the variable scope that is in effect when they are invoked." - David Flanagan, JavaScript: The Definitive Guide

Scope

var car = "Ford"; // global

function getCar() { // global function

    return car;

}

getCar(); // "Ford"

Scope examples adapted from JavaScript: The Definitive Guide

Scope

var car = "Ford"; // global

function getCar() { // global function

    var car = "Chevy"; // local

    return car;

}

getCar(); // "Chevy"

Scope

var car = "Ford"; // global

function getCar() { // global function

    var car = "Chevy"; // local

    function foo() { // local
    
        return car;

    }

    return foo();

}

getCar(); // "Chevy"

Scope

var car = "Ford"; // global

function getCar() { // global function

    var car = "Chevy"; // local

    function foo() { // local

        var car = "Toyota";
    
        return car;

    }

    return foo();

}

getCar(); // "Toyota"

Scope

var car = "Ford"; // global

function getCar() { // global function

    var car = "Chevy"; // local

    function foo() { // local
    
        return car;

    }

    return foo; // return the function, not value

}

getCar()(); // "Chevy"

So what's a closure?

Closures

Function Object

+
Scope
=
Closure

All functions are closures, because they all have scope!
 

Closures

However, closure usually refers to a function which is called outside of the scope chain it was defined in.

function foo() {
    var biz = "baz";

    function bar() {
        return biz;
    }

    return bar;
}

var closure = foo();

closure(); // "baz"

Closures

Closures are often used to keep variables out of the global scope and to protect them from other JavaScript on the page.

function clickCounter() {
    var numclicks = 0;

    // only way to alter numclicks after clickCounter() is called
    window.addEventListener("click", function() {
        numclicks++;
    });

    return function () {
        return numclicks;
    }
}

var howManyClicks = clickCounter();

howManyClicks(); // only way to get number of clicks!

IIFE

  • Stands for "Immediately Invoked Function Expression"
  • Just means creating and invoking an anonymous function in one step.
// Parentheses just tell JavaScript that there is an expression here
(1+1) // => 2
var x = (1+2); // x now equals 3

// a function can be used inside an expression
// this expression just returns a function. not useful by itself
(function() {return "foo";}); // => function anonymous()

// more useful if we actually assign it to something
var x = (function() {return "foo";});
x(); // => "foo"

// So an IIFE is when we return a function from an expression and call it
var x = (function() {return "foo";})();
x; // => "foo";

Creating an API

var myApi = (function() {
    var some_number = 5;

    function somePrivateFunction() {
        console.log('Doing something behind the scenes with the number ' + some_number);
    }

    return {
        doAThing: function() {
            return 'Just doing a thing.';
        },
        doAnotherThing: function() {
            somePrivateFunction();
            return 'Doing another thing';
        }
    };
}());

myApi.doAThing(); // "Just doing a thing."

myApi.doAnotherThing(); // Doing something behind the scenes with the number 5
                        // "Doing another thing"

Intro to JS Closures

By Daniel Abernathy