Telegraph Prep+ Week 4

Anonymous Functions

Closures

Who are you?

  • Have a mastery of
    JS arrays, objects, and loops, functions. 
  • Good understanding of scope, anonymous functions.
  • Know what higher order functions, and callbacks are.

Week 4 will cover

  • Anonymous functions (and why they're important.)
  • Closures & Closure scope.
  • Higher order functions, and buliding libraries. 

Anonymous Functions

anonymous function

function(item) {
  return item * 3;
}

An anonymous function has no name after the 'function' keyword

 

Often passed as callbacks to higher order functions

(we'll use these often in this class)

anonymous function

function(item) {
  return item * 3;
}

Anonymous functions are important because:

1. They are widely used in the coding community. If you don't know how to approach one you'll be considered a n00b.

 

2. They allow us to save space in memory by calling a function only when necessary (we'll get to this in a second).

anonymous function: Invocation

function(item) {
  // 10 is going to take the place of the parameter, item.
  return item * 3;
}(10) 
// ??

An anonymous function is much more than an 'unnamed' function. 

In programming, creating something without assigning it means it's not stored in memory. 

If it is not stored in memory, how do we call the function?

anonymous function: use case

function(item) {
  return item * 3;
}()

Calling a function on the exact line doesn't do us much good. Functions are supposed to be recipes that are used over and over again.

 

Can you think of a way we can replicate that important functionality without naming the function?

anonymous function & Higher ORder Funcs

// not useful
function(item) {
  return item * 3;
}(10);

var multItem = function(item, callback){
    return callback(item);
};

// pretty useful
var thirty = multItem(10, function(item){
  return item * 3
});

You guessed it! Passing it into a higher order function allows the anonymous function to be called whenever that function is called.

anonymous function & Higher ORder Funcs

// pretty useful
var thirty = multItem(10, function(item){
  return item * 3
});

// VERY useful
var multByAnyNumber = function(item, n){
    return multItem(item, function(item){
      return item * n
    });
};

var twenty = multByAnyNumber(2, 10); // 20
var thirty = multByAnyNumber(5, 6); // 30

An even better use case below, and an intro into what you'll be working toward this week

Named vs Anonymous

//Anonymous function saved into a variable
var nameImprover = function (name, adj) {
  return 'Col ' + name + ' Mc' + adj + ' pants';
};

//named function
function nameImprover(name, adj) {
  return 'Col ' + name + ' Mc' + adj + ' pants';
}

// anonymous function
function (name, adj) {
  return 'Col ' + name + ' Mc' + adj + ' pants';
};

// they all work!

Key Takeaways

  • ANONYMOUS FUNCTIONS AND NAMED FUNCTIONS WORK *ALMOST* THE SAME WAY - SO DON'T BE AFRAID OF THEM.
    
    
  • ANONYMOUS FUNCTIONS CAN ONLY BE INVOKED ON THE LINE 
    THAT THEY ARE CALLED.
    
    
  • ONE OF THE BEST USE CASES FOR ANONYMOUS FUNCTIONS ARE WHEN YOU ARE PASSING THEM INTO, OR RETURNING THEM FROM A HIGHER ORDER FUNCTION.

 

 

EXERCISES

  • Repo:

  • New Pairs
  • References:

https://github.com/TelegraphPrep/week-4-closures

http://slides.com/telegraphprep/telegraphprepweek3-13#/1

scopes, pt 2

 
 
var firstAlert = function(){
  var x = 'Secret Message';
  
  var alerter = function(){
    alert(x);
  };
  
  alerter();
};
firstAlert();

Nested Inner Function

Inner function called within outer function

Let's walk through this code together as though we were the JS interpreter...

 
var firstAlert = function(){
  var x = 'Secret Message';
  
  var alerter = function(){
    alert(x);
  };
  
  setTimeout(alerter, 1000);
  console.log('will still run right after');
};

firstAlert();

Nested Inner Function

Inner func called within browser-land

Let's pop this code into the console and see what happens...

 
var firstAlert = function(){
  var x = 'Secret Message';
  
  var alerter = function(){
    alert(x);
  };
  
  return alerter;
};

var alert1 = firstAlert();
alert1();

Returned Inner Function

Inner function called where?

var firstAlert = function(){
  var x = 'Secret Message';
  
  var alerter = function(){
    alert(x);
  };
  
  return alerter;
};

var alert1 = firstAlert();

called outside of outer function

var add = function(num){
  var num1 = num;

  var addToNum1 = function(num2){
    return num1 + num2;
  };

  return addToNum1;
};

var alwaysAdd2 = add(2);

Returned Inner Function

var add = function(num){
  var num1 = num;

  var addToNum1 = function(num2){
    return num1 + num2;
  };

  return addToNum1;
};

var alwaysAdd2 = add(2);
alwaysAdd2(3); //??
var add = function(num){
  var num1 = num;

  var addToNum1 = function(num2){
    return num1 + num2;
  };

  return addToNum1;
};

var alwaysAdd2 = add(2);
alwaysAdd2(3); //5
var alwaysAdd10 = add(10);
var add = function(num){
  var num1 = num;

  var addToNum1 = function(num2){
    return num1 + num2;
  };

  return addToNum1;
};

var alwaysAdd2 = add(2);
alwaysAdd2(3); //5
var alwaysAdd10 = add(10);
alwaysAdd10(3); //??
var add = function(num){
  var num1 = num;

  var addToNum1 = function(num2){
    return num1 + num2;
  };

  return addToNum1;
};

var alwaysAdd2 = add(2);
alwaysAdd2(3); //5
var alwaysAdd10 = add(10);
alwaysAdd10(3); //13

questions?

 

Congratulations! You now know closures!

 

Why are closures important?

  • access private variables (ex: module pattern)
  • partial application of arguments (currying)*
  • recursion involving memoization*

 

*advanced topics not covered in this class

Closure Definition

Closure functions are declared inside outer functions (nested) and invoked in a context outside of the one they were created in.

They retain access to a closure variable from the context the function was created in.

Remember a closure consists of

TWO key components:

  • closure function
  • closure variable

Recipe: creation

1. Create your parent function.

2. Define some variables in the parent's local scope.

     (they can be accessed by the child function)

3. Define a function inside the parent function.

     (aka defining a "child" function or "nested" function)

4. Return that child function from inside the parent.

function outerFunc() {
  var parentVar = "local to parent";
  function innerFunc() {
    return parentVar + ' but accessed by child!';
  };
  return innerFunc;
}
1.
2.
3.


4.

closure variable

closure function

RECIPE: Execution

function outerFunc() {
  var parentVar = "local to parent";
  function innerFunc() {
    return parentVar + ' but accessed by child!';
  };
  return innerFunc;
}

// STEP 1 - Invoke the parent function.
var example = outerFunc();
console.log(example);
// We see example now stores the child function.

// STEP 2 - Invoke the child function.
var result = example();
console.log(result);
// What's the end result?

Closure Definition,  revisited

Closure functions are declared inside outer functions (nested) and invoked in a context outside of the one they were created in.

A: outside of scope it was created in

Q: where is closureFunc getting invoked?

var firstAlert = function(){
  var x = 'Secret Message';
  var alerter = function(){
    alert(x);
  };
  alerter();
};
firstAlert();
var firstAlert = function(){
  var x = 'Secret Message';
  var alerter = function(){
    alert(x);
  };
  return alerter;
};
firstAlert();
var firstAlert = function(){
  var x = 'Secret Message';
  var alerter = function(){
    alert(x);
  };
  return alerter;
};
firstAlert()();

Closure Definition,  revisited

Closure functions retain access to closure variables from the context the function was created in.

var firstAlert = function(){
  var x = 'Secret Message';
  var alerter = function(){
    alert(x);
  };
  return alerter;
};
var myAlert = firstAlert();
// myAlert still has access to x

Gotcha!?

var sayAlice = function(){

  var makeLog = function() {
    console.log(alice);
  };

  var alice = 'Why hello there, Alice!';

  return makeLog;
};

var log = sayAlice();

log(); //??

What will we see in the console?

Walk through the code as the JS interpreter would

Scope is created at runtime

var makeStopwatch = function(){
  
  var elapsed = 0;
  var increase = function(){ elapsed++; };
  setInterval(increase, 1000);

  var stopwatch = {
    getTime: function() { return elapsed; }
  };

  return stopwatch;

};

var watch1 = makeStopwatch();
// wait 3 seconds...
var watch2 = makeStopwatch();
watch1.getTime() - watch2.getTime(); //??

how many "elapsed" variables are created?

everytime makeStopwatch is invoked, a new closure comes into existence

key takeaways

Closures functions are nested inside outer functions and retain access to closure variables in the context the function was created in

 
function outerFunc() {
  var closureVar = "Only the closureFunc can access me!";
  function closureFunc() {
    console.log('closureVar says:', closureVar);
  }
  return closureFunc;
};

var innerFunc = outerFunc();
innerFunc(); // this is the closure function
// --> "closureVar says: Only the closureFunc can access me!" 

Questions

Exercise Time!

Repo:

Same Pairs

Slides: 

https://github.com/TelegraphPrep/week-4-closures

http://slides.com/telegraphprep/telegraphprepweek3-13#/2

Anonymous Functions Review & Closures

By telegraphprep

Anonymous Functions Review & Closures

An introduction to functional programming

  • 827