Skip to content

sf-pocket-gophers-2015/iifes_modules_closures

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 

Repository files navigation

IIFEs, Closures, Modules

These are the syntactical gymnastics we have to go through to get useful OO stuff in js, such as

  • private state
  • public API
  • encapsulation (global state is bad. why???)
  • namespacing

Pertinent js recap

  • js only has function scope
  • In js, functions are first order objects
    • functions can be passed as params
    • functions can be returned as the result of expressions
    • variables can hold functions
  • Functions are invoked with ()
  • Anything wrapped in () becomes an expression

Function declaration and invocation

// function declaration
function someName() { 
  // ...
}
// function expression
// (defines an anonymous function and assigns it to a var)
var someName = (function() {
  // ...
});
// function invocation
someName();

IIFE (iffy)

This is an IIFE

(function() {
  //...
})();
  • An anonymous function expression
  • The parens around the declaration turn it into an expression
  • The parens at the end cause it to be immediately invoked
  • Avoids polluting global scope
  • Allows us to hide private state
  • Avoids variable hoisting
(function() {
  var something = "my internal stuff";
  //...
})();

// what will the following line log?
console.log(something);

Closures

  • In js, if we use the function keyword inside another function, we are creating a closure
  • The local variables in the inner function can remain accessible after returning from the outer function
  • A closure is a function having access to the parent scope, even after the parent function has closed
  • A closure is a special kind of object that combines two things: a function, and the environment in which that function was created
  • Environment consists of any local variables that were in-scope at the time that the closure was created
var returnData = (function() {
  // only created once
  var largeDataSetTakesForeverToGet = [1,2,3]; // this could be an ajax call
  
  return function() { 
    console.log(largeDataSetTakesForeverToGet) 
  };
})();

// getting that same variable back each time
returnData();
returnData();
returnData();
  • This internal state can be mutable, but only through API we provide
var add = (function () {
    var counter = 0;
    return function () {return counter += 1;}
})();

add();
add();
add();

Closure as function factory

  • We can initialize a closure with state
  • A closure with its own state is created for each function invocation
function messageAfter(seconds) {
  return function(thingToMessage) {
    return 'Waited ' + seconds + ' seconds to say: ' + thingToMessage;
  };
}

var messageAfter5Seconds = messageAfter(5);
var messageAfter2Seconds = messageAfter(2);

messageAfter5Seconds("pocket gophers");
messageAfter2Seconds("pocket gophers");

messageAfter(7)("pocket gophers");
messageAfter(453764576)("pocket gophers");

JS Module Pattern

  • We can use IIFEs and closures as building blocks for modules
  • We can hide internal state
  • We can expose a public API
  • We can provide namespacing
  • This is a standard pattern for writing JS libraries
// mathy.js
var mathy = (function() {
  
  var topSecret = "shhhhhh";
  
  var factorial = (function(n) { 
    return Math.factorial(n);
  });
  
  var square = (function(n) {
    console.log("square");
    secretFunctionTime();
    console.log("square out");
    return n*n;
  });
  
  var log = (function(n) {
    return Math.log(n);
  });
  
  var secretFunctionTime = (function() {
    console.log(topSecret + ", can't call this from outside");
  });
  
  return {
    factorial: factorial,
    square: square,
    log: log
  }
})();
// ...
// > mathy.square(4);
// 16
// > mathy.secretFunctionTime
// undefined
// > mathy.topSecret
// undefined

Resources

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published