Skip to content

Latest commit

 

History

History
408 lines (253 loc) · 25.4 KB

download (13).md

File metadata and controls

408 lines (253 loc) · 25.4 KB

Skip to main content

Web Fundamentals

1.  User Interface and Git

2.  Advanced CSS and Intro JavaScript

3.  JavaScript Fundamentals

4.  WEB Unit 1 Build

Web Fundamentals

1.  User Interface and Git

2.  Advanced CSS and Intro JavaScript

3.  JavaScript Fundamentals

4.  WEB Unit 1 Build

Advanced Array Methods

This module will give you practice with advanced array methods such as .map, .filter, and .reduce and introduce you to the idea of callbacks. Both advanced array methods and callbacks will make it easier to interact with large data sets, like we started in the last sprint. As you progress in your journey as a web developer, these will likely become some of your favorite tools for both displaying data, and dealing with user data.

At the end of this module, you should be able to:

  • demonstrate the proper use a of a callback function by passing a function to another function as a parameter
  • demonstrate ability to use `.map` `.reduce` `.filter` and describe their use cases

Pro Tip

Omit needless words.

Strunk and White

Prepare

Review each preclass resource before class.

Learn

Learn to demonstrate the proper use a of a callback function by passing a function to another function as a parameter

Callback functions come from a programming paradigm known as functional programming (FP). Is not a new paradigm nor is it unique to JavaScript. In fact, many have wondered (due to its dynamic nature) whether JavaScript is an Object Oriented language or a Functional Programming language. The answer to that is simply, both. We get the ability to choose the patterns to use in order to accomplish tasks.

That really is all we’re trying to do here: provide the computer a set of instructions to achieve a task. And the make up of many many tasks simply becomes… software.

At the end of the day, the language isn’t written for the computer, that would be binary. The language we use as developers was written for us, so we as developers get to choose the paradigm we are to use to achieve the task.

So, callback functions are just functions that are passed into other functions as arguments. And the concept is so commonly used throughout the JavaScript language that one day you’ll look back and barely remember a time when you didn’t know how to use them.

Overview

You’ll hear these words everywhere: “Functions in JavaScript are first-class citizens.” And if you’re like me, you’ll get puzzled, trying to dissect meaning from those words.

Simply put, this means that functions in JavaScript are a Type like any other Type (Boolean, String, Number), and they can be passed around as arguments to other functions.

Take the following example into consideration:

const functionFeeder = function(callback) {
  callback('Hello from the inside of Function Feeder');
};

What we have done here is define a function called functionFeeder and passed it a parameter called callback. So when functionFeeder is invoked, we can feed it a function as an argument. That function, in turn, will run the string Hello from the inside of Function Feeder back to the callback function it receives. And thus, when we call functionFeeder we can handle that string that comes back to us like so:

functionFeeder((string) => { // invoking the function
  alert(string); // alert a function that pops up a box in the browser.
});

functionFeeder respectively becomes what is known as a higher-order function or a callBack function, allowing it to take in a function as a parameter and executes a function when called with a function as the argument.

Let’s take a look at a few more examples.

  function sayHello(name) {
    console.log(`Hello, ${name}`);
  }

sayHello is a function with one purpose, to say hello to the name that is passed into it. Because we’ve built a function with such a straightforward goal, we can use it over and over again. Once we set up a function that will define the name we want passed to sayHello, all we’ll have to do is pass it to our function and let it perform is routine / action.

 function callSayHelloWithLars(callback) {
    const innerName = 'Lars';
    callback(innerName);
  }

The callback in the above function will become sayHello when we invoke it like this:

 callSayHelloWithLars(sayHello);

And callSayHelloWithLars executes sayHello as it’s callback.

I could re-use sayHello in another context now. Check it out.

function callSayHelloWithRyan(callback) {
  const newName = 'Ryan';
  callback(newName);
}

Now let’s combine a few of the things we’ve learned today. I mentioned that callbacks are used everywhere. They’re even used in our Array methods… ALL OF THE TIME! EVERYWHERE! In the case of .forEach(), an iterator function, we use a callback to access the items in the array that come back with each pass.

const items = ['feather', 'coupon', 'cup', 'drill'];

We could use a native for loop to loop over this list and log out every item.

for(let i = 0; i < items.length; i ++) {
  alert(items[i]);
}

This works for sure! But we have .forEach built into the language to allow us not to have to write that every time. So, we could do something like this to clean it up a bit.

items.forEach(item =>  alert(item) );

NOTICE this part is the callback item => alert(item)

This is some fancy syntax that we will continue to go over as the week progresses.

Follow Along

So now lets practice some things together. First, let’s create a list of elements we want to play around with as our data — literally, elements.

const elements = ['earth', 'wind', 'fire', 'water'];

Remember that with functions we can pass as many parameters as we want to them. So let’s create a couple of functions that we can use to consume this list of elements.

Create a function called show first that passes back the first item in the given array.

function showFirst(array, callback) {
  callback(array[0]);
}
showFirst(elements, (firstItem) => {
  alert(firstItem);
});

Create a function like ‘shoFirst’, but this time, show the length of the array passed.

function showLength(array, callback) {
  callback(array.length);
}
showLength(elements, (length) => {
  alert(length);
});

Now, let’s use forEach again to loop over our array and alert each item in the array.

elements.forEach(element => alert(element));

Remember map? The most significant difference between .forEach and .map is that map returns a new array of elements while in turn passing each element back to the callback.

const newArray = elements.map(item => 'Element: ' + item);
Challenge

Complete the following exercises included here in this JSBin Callbacks.

Dig Deeper

Learn to demonstrate ability to use `.map` `.reduce` `.filter` and describe their use cases

Earlier on we covered what callbacks are and gave you ample practice to get familiar with their use. Today we’re going to dive deeper and cover some more crucial examples of callback functions as well as get you the reps you need.

The callback is such a fundamental piece of the JavaScript language that you need to have a good grasp of if you want to be able to push your skills further.

Overview

In this lesson, we’re going to get a lot of practice playing around with data and transforming it with more loop-like functions. Data transformation, after all, is one of the main goals in our jobs as web engineers since we ultimately display data in some way that makes sense to the end user.

Functional programming is a very fun programming paradigm because it lends itself to this idea of immutability. Which is basically creating objects (variables, functions, etc) that can’t be changed by other code later on in a codebase. When we get to Redux, you’ll learn all about immutability, and you’ll have a better grasp of what that concept means by going through some of these exercises today.

First, let’s talk about what functions we have at our disposal to make variables and functions immutable. The .map .filter and .reduce functions are commonly used to achieve immutability and take a set of data and transform it in some way.

Let’s consider the following data set, an array of object literals. You will often see this data type stored in imported .JSON files, including in guided practice today. Here though, our data is written inline, which is also fine.

const data = [
  {"city":"seattle", "state":"WA", "population":652405, "land_area":83.9},
  {"city":"new york", "state":"NY", "population":8405837, "land_area":302.6},
  {"city":"boston", "state":"MA", "population":645966, "land_area":48.3},
  {"city":"kansas city", "state":"MO", "population":467007, "land_area":315}
];

Let’s say we want to represent this data in some way that is useful to our users.

.map

.map asks us to create an array with just city and state names. We could do this by copying just city and state data into a new array in a for loop like so.

const cityStates = [];
for(let i = 0; i < data.length; i++) {
  let mappedObj = {};
  mappedObj.city = data[i].city;
  mappedObj.state = data[i].state;
  cityStates.push(mappedObj);
  mappedObj = {};
}

That works! It’s a simple solution, and simplicity is the gold standard for programming. That said, it’s a bit hard to read, so is there a better way? absolutely!

.map is a higher-level function that takes 2 arguments, a callback and a context. The callback is a function to be called “for” each item in the array, the context is the object value(s) to be used. You’ll often people say they are going to “map” some data. That means they are going to apply a set of rules to a data set. For example “mapping” the array [1,2,3] times two would result in [2,4,6].

.map annotated code

The map function can also take in a callback that passes back a couple of things to us. The three things you’d get back from a callback passed to Map would be:

  • The current item of the array state
  • The current index of the current item index
  • The entire array data

In the example below, the value given in the callback is state since task 1 asks us to look at state data.

const mappedCityStates = data.map((state) => {
  return {'city': state.city, 'state': state.state};
});

.filter

What if we only want to see states who’s population is greater than 650,000? With your prior JavaScript knowledge it might make sense to create something like this:

const largeStates = [];
for(let i = 0; i < data.length; i++) {
  if(data[i].population >= 650000) {
    largeStates.push(data[i]);
  }
}

Now, we can use .filter to iterate over all items in the array and return only what we want. This is useful anytime we need a subset of a larger group of data.

Filter takes exactly the same arguments as .map, namely: value, index, and array.

const filterLargeStates = data.filter((state) => {
  return state.population >= 650000;
});

Same results and cleaner code. The line return state.population >= 650000; tells JavaScript to return an object whose population is higher than 650,000, and in turn, pass that object to a new array. The other objects (states with a population lower than 650,000) will be ignored since they don’t pass this logic test. Think of that line reading like this: IF state.population is greater than or equal to 650000 THEN push it into a new array ELSE do nothing.

.reduce

Reduce is slightly tricker than .map and .filter because it requires use of different arguments. Its powers though, are endless. Essentially, reduce works to algorithmically simplify an array down to a single value.

Let’s say we want a single number of all of the state’s populations added together. With the most basic JavaScript we might do something like this.

let statePopulations = 0;
for(let i = 0; i < data.length; i++) {
  statePopulations += data[i].population;
}

This is a relatively simple algorithm, but let’s look at it in terms of the reduce function now. .reduce allows us to reduce all data to a single value. It is a perfect use here because we can aggregate that data and use .reduce to do so for us.

const reduceStatePopulations = data.reduce((total, state) => {
  return total += state.population;
}, 0);

This is more succinct, but a lot is going on here. Importantly, we pass 0 as a second argument to our reduce function. This argument will become the starting value of our total and, if not provided, would default to the first item in the array. In this case, that would be disastrous because the first item of our array is an object, and we’re trying to reduce our total to a single numerical value. Instead, we can provide a starting value for total and thus set what our data type will reduce to. Remember that total also gets memorized or remembered by our function each pass.

Screen Shot 2019-12-03 at 11.34.39 AM

Note, the function will run without the 0 pictured above, but will default to starting accumulation at the first number in the array, which often doesn’t make sense

The four items that get passed back from our callback function when using .reduce are:

  • The current value of the total aggregated value.
  • We set the initial value at the end of the function. In this case, we set it to 0.
    • This could be any value, though.
  • The current item in the array.
  • The index again.
  • The full array.

To sum up. These functions are fantastic and allow us to write clean, reusable code in a functional programming style. They give us the power to represent our data in an enjoyable way. As you get more and more used to using these functions, you’ll get the ability to use them in very complex situations that will eventually save your bacon. For now, let’s go practice. Check out the challenge on JSBin. Go play around and see if you can create some new data sets out of the provided data.

Follow Along

Let’s take our same Data Set from earlier and play around with it some more.

const data = [
  {"city":"seattle", "state":"WA", "population":652405, "land_area":83.9},
  {"city":"new york", "state":"NY", "population":8405837, "land_area":302.6},
  {"city":"boston", "state":"MA", "population":645966, "land_area":48.3},
  {"city":"kansas city", "state":"MO", "population":467007, "land_area":315}
];
  1. Use .map to create an array of integers that represent all the states names and populations.

The callback function here is what’s enclosed in the return function. state is the value, or element(s) that will be processed.

const mappedCityStates = data.map((state) => {
  return {'state': state.state, 'population': state.population};
});
  1. Use .filter to create an array of states who’s land_area is larger than 50 units. Just like with map, we use arrow function syntax to dictate a return. Similarly, state is the value, or element(s) that will be processed.

    const filterLandArea = data.filter((state) => { return state.land_area >= 50; });

  2. Use .reduce to create an array of the states land_area reduced to the mean average of all the state’s combined.This example uses similar parameters, only adds the counter total to accumulate the sum.

    const landAreaAverage = data.reduce((total, state) => { let sum = total + state.land_area; console.log(sum, total, state); return sum; }, 0); const average = landAreaAverage / data.length;

Challenge

Complete the following exercises using .map, .filter, .reduce.

Code found here

Dig Deeper

Project

  • In this challenge you will work with a data set summarizing every world cup game from 1930-2014. You will use advanced array methods and callbacks to dig up interesting statistics about these games.

Review

Class Recordings

You can use class recordings to help you master the material.

  • Advanced Array Methods for WebPT22 w/Nathan Braun

    This module will give you practice with advanced array methods such as .map, .filter, and .reduce and introduce you to the idea of callbacks. Both advanced array methods and callbacks will make it easier to interact with large data sets, like we started in the last sprint. As you progress in your journey as a web developer, these will likely become some of your favorite tools for both displaying data, and dealing with user data.

  • All previous recordings

Demonstrate Mastery

To demonstrate mastery of this module, you need to complete and pass a code review on each of the following:

  • Objective challenge:

    Complete the following exercises included here in this JSBin Callbacks.

  • Objective challenge:

    Complete the following exercises using .map, .filter, .reduce.

    Code found here

  • Project: FIFA Challenge