Loop-a-palooza

Revisiting loops, callbacks, and higher order functions

 

Higher Order Functions Review

Explaining Each

Expanding Each

Loops on Loops on Loops

Overview

Higher ORder Functions

Review

HIgher Order functions

A higher order function is a function that either:

 

 

  • Takes a function as an argument.
    
    
  • Returns a function to be used at a later time.

 

This week we are focused on the first one.

each

Allow me to reintroduce myself, my name is each.

var each = function(collection, callback){
 // loops through the collection
 for (var i = 0; i < collection.length; i++){
    // passes each element inside of collection
    // to the callback
    callback(collection[i])
 }
};

each

each in action

var each = function(collection, callback){
    for (var i = 0; i < collection.length; i++){
     // passing each array element into our callback
      callback(collection[i]); 
    }
}

var bestSentence = ['I', 'love', 'javascript'];

each(bestSentence, function(word){
  console.log(word.toUpperCase());
});

// 'I'
// 'LOVE'
// 'JAVASCRIPT'

The anonymous function corresponds to the callback parameter we specify in each.

The `word` parameter corresponds with the argument being passed into our callback.

each

What happens when our callback returns?

var each = function(collection, callback){
    
    for(var i = 0; i < collection.length; i++){
        callback(collection[i]);
    }
}

var numbers = [1, 2, 3, 4, 5];

each(numbers, function(element){
    // returning instead of console.logging
    return element;
});
var each = function(collection, callback){
    
    for(var i = 0; i < collection.length; i++){
        console.log(callback(collection[i]));
    }
}

var numbers = [1, 2, 3, 4, 5];

each(numbers, function(element){
    // returning instead of console.logging
    return element;
});

Let's throw a console.log inside of our `each` so that we can see what's being returned.

each

what is the purpose of each then?

Definition: The Each function provides its callback access to each element inside of a collection.

That's it.

No really, that's it.

Multby2

multBy2 takes an array of numbers and returns a new array with each element multiplied by 2
var multBy2 = function(array) {

	var results = [];
	for (var i = 0; i < array.length; i++){
		results.push(array[i] * 2);
	}
	return results;
};

Let's replace our for-loop with our 'each' function

var multBy2 = function(numbers) {

	var results = [];

	each(numbers, function(number){
		results.push(number * 2);
	});

	return results;
};

Our `ea` function makes this code more expressive and clean.

Multby2

multBy2 in depth:
var multBy2 = function(numbers) {

	var results = [];
	each(numbers, function(number){
		results.push(number * 2);
	});
	return results;
};

The callback has access to the `results` array in its parent scope

Thanks to each, the callback also has access to each number in the `numbers` array.

Multby2

multBy2 in action:
var multBy2 = function(numbers) {

	var results = [];
	each(numbers, function(number){
		results.push(number * 2);
	});
	return results;
};

var nums = [1, 2, 3, 4, 5];

var numsMult2 = multBy2(nums);

Let's throw this in the console and see what we get.

Expanding each

Expanding the functionality of our loop function

Expanding each

Our current loop function

var each = function(collection, callback){
    for (var i = 0; i < collection.length; i++){
      callback(collection[i]);
    }
};

We've been building functions where loop can only take an array, but what about objects?

Expanding each

Expanded to work with objects or arrays

var each = function(collection, callback){

  if (Array.isArray(collection){
    for (var i = 0; i < collection.length; i++){
      callback(collection[i]);
    }
  } else if (typeof collection === 'object'){
    for (var key in collection){
      callback(collection[key]);
    }
  }
};

Expanding each

New loop in action

var obj = {name: 'Albrey', favoriteColor: 'blue'};

each(obj, function(value){
	console.log(value);
}); 

// 'Albrey', 'blue'

Expanding each

But that's not it...

var obj = {name: 'Albrey', favoriteColor: 'blue'};

each(obj, function(value){
	console.log(value);
}); 

// 'Albrey', 'blue'

When do we ever just deal with values?

Let's expand our loop even further to support passing keys/indexes to our callback.

Expanding each

Expanding loop even further

var each = function(collection, callback){

  if (Array.isArray(collection)){
    for (var i = 0; i < collection.length; i++){
      callback(collection[i]);
    }
  } else if (typeof collection === 'object'){
    for (var key in collection){
      callback(collection[key]);
    }
  }
};

Passing the current key/index to our callback.

var each = function(collection, callback){

  if (Array.isArray(collection)){
    for (var i = 0; i < collection.length; i++){
      callback(collection[i], i);
    }
  } else if (typeof collection === 'object'){
    for (var key in collection){
      callback(collection[key], key);
    }
  }
};

Expanding each

Expanded loop in action

var obj = {name: 'Albrey', favoriteColor: 'blue'};

each(obj, function(value, key){
	console.log('this is the value:', value);
	console.log('this is the key:', key);
        
}); 

// "this is the value: Albrey"
// "this is the key: name"
// "this is the value: blue" 
// "this is the key: favoriteColor"

Specifying `key` parameter in our callback.

Expanding each

Can we reference key and not value?

var obj = {name: 'Albrey', favoriteColor: 'blue'};

each(obj, function(key){
	console.log('we only want the key', key);
        
}); 

// "we only want the key: Albrey"
// "we only want the key: blue" 

We must insert 2 parameters in order to access the key.

var obj = {name: 'Albrey', favoriteColor: 'blue'};

each(obj, function(value, key){
	console.log('we only want the key', key);
        
}); 

// "we only want the key: name"
// "we only want the key: favoriteColor" 

loops on loops

Because sometimes one is just not enough.

NEsted Data

var person = {
    name: "Jon Tippens",
    greatestFear: "Those frozen biscuit things.",
    dateUsedAgainstHim: "2/02/1997",
};

for (var characteristic in person){
    console.log(person[characteristic]);
};

// 'Jon Tippens'
// "Those frozen biscuit things."
// "2/02/1997"
This data structure is not nested in another datastructure

NEsted Data

var people = [{
    name: "Jon Tippens",
    greatestFear: "Those frozen biscuit things.",
    dateUsedAgainstHim: "2/02/1997",
    }, {
    name: "Albrey Brown",
    greatestFear: "Brain aneurysm.",
    dateUsedAgainstHim: "03/30/1991",
    }];
Our original person object is nested in the 'people' array
var jon = {
    name: "Jon Tippens",
    greatestFear: "Those frozen biscuit things.",
    dateUsedAgainstHim: "2/02/1997",
}; 
var albrey = {
    name: "Albrey Brown",
    greatestFear: "Brain aneurysm.",
    dateUsedAgainstHim: "03/30/1991",
};

var people = [jon, albrey]
Let's make this look more palatable
Our two persons are nested in our people array.

Nested Data

How do we loop through each object?
var people = [jon, albrey]

for (var i = 0; i < people.length; i++){
    console.log(people[i]);
};
 
// { name: "Jon Tippens", greatestF...}
// { name: "Albrey Brown", greatestF...}
Looping through the `people` array allows us access to each `person`.
We need a second for-loop to loop through the characteristics in our persons

Double For Loop

Add another for loop
var people = [jon, albrey]

for (var i = 0; i < people.length; i++){
    var person = people[i];
    for(var characteristic in person){
        console.log(person[characteristic]);
    }
}
// Jon Tippens
// Those frozen biscuit thingies
// 2/02/1997
// Albrey Brown
// Brain aneurysm
// 03/30/1991
instead of `person`, we can access people[i]
var people = [jon, albrey]

for (var i = 0; i < people.length; i++){
    
    for(var characteristic in people[i]){
        console.log(person[characteristic]);
    }
}
// Jon Tippens
// Those frozen biscuit thingies
// 2/02/1997
// Albrey Brown
// Brain aneurysm
// 03/30/1991

Double For Loop

Make Sense?

GReat!

Let's take it up a notch 

Double Loop

Anything you can do I can do better...

var people = [jon, albrey]

for (var i = 0; i < people.length; i++){

    for(var characteristic in person){
        console.log(person[characteristic];
    }
}
Remember, we're supposed to be ridding the world of for-loops
How can we use our `loop function to achieve the same thing?
var people = [jon, albrey]
// loop through the people array
loop(people, function(person){;
    
    for(var characteristic in person){
        console.log(person[characteristic]);
    }
});
var people = [jon, albrey]
// loop through the people array
loop(people, function(person){;
    
    loop(person, function(characteristic){
        console.log(characteristic);
    });
});
// Jon Tippens
// Those frozen biscuit thingies
// 2/02/1997
// Albrey Brown
// Brain aneurysm
// 03/30/1991
First, let's replace our first for-loop with a `loop`
Then, we can replace our for-in loop with a `loop` function

Double Loop

Break it down now

var people = [jon, albrey]

loop(people, function(person){;
    console.log(person)
});

// { name: "Jon Tippens", greatestF...}
// { name: "Albrey Brown", greatestF...}
Looping through the `people` array allows us access to each `person`.
var people = [jon, albrey]
// loop through the people array
loop(people, function(person){;
    
    loop(person, function(characteristic){
        console.log(characteristic);
    });
});
// Jon Tippens
// Those frozen biscuit thingies
// 2/02/1997
// Albrey Brown
// Brain aneurysm
// 03/30/1991
We can then pass each `person` to our loop, and console.log

Double Loop

one more time

var people = [jon, albrey]

for (var i = 0; i < people.length; i++){

    for(var characteristic in person){
        console.log(person[characteristic];
    }
}
Remember, we're supposed to be ridding the world of for-loops
How can we use our `loop function to achieve the same thing?
var people = [jon, albrey]
// loop through the people array
loop(people, function(person){;
    
    for(var characteristic in person){
        console.log(person[characteristic]);
    }
});
var people = [jon, albrey]
// loop through the people array
loop(people, function(person){;
    
    loop(person, function(characteristic){
        console.log(characteristic);
    });
});
// Jon Tippens
// Those frozen biscuit thingies
// 2/02/1997
// Albrey Brown
// Brain aneurysm
// 03/30/1991
First, let's replace our first for-loop with a `loop`
Then, we can replace our for-in loop with a `loop` function

Exercises

COntinue working with our partner on the Infinite Loops exercises.

 

You can find them at telegraphprep.github.io/part3.html

Infinite Loops

By telegraphprep

Infinite Loops

Loops, callbacks, and higher order functions.

  • 1,468