Find file History
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
..
Failed to load latest commit information.
README.md
js-array-iteration-methods_notes.pdf

README.md

LESSON: js-array-iteration-methods


2018-06-12

Tags: javascript, arrays, iteration, arrow functions, callbacks, higher-order functions

OBJECTIVES

  • Write callbacks to pass to array methods
  • Call array methods and pass callback as an argument
  • Write functions using array methods to add functionality.

VOCABULARY

Reference Types: A type of variable that refers to a collection of memory addresses, ie a collection of different values in memory. In Javascript, Objects and Arrays are both reference types.

First-Class Object: A first class object is an entity that can be dynamically created, destroyed, passed to a function, returned as a value, and have all the rights as other variables in the programming language have. Functions are first-class objects in Javascript which means that they can be treated like other variables, ie be part of an Array, passed as an argument, etc.

Callback Function: A callback function (also called a callack) is a function passed to another function as an argument such that the callback can be run from within that function.

ES6: ES6 is short for ECMA Script 6, where ECMA is short for European Computer Manufacturers Association. ECMA is the organization that releases standards for various programming languages, and they determine what new features and changes will be released in new versions of these languages. ECMA Script is actually just the ECMA standard for Javascript. ES6 is a recently released Javascript standard that is supported in most modern browsers, and introduced a ton of new features and syntax (see here for more).

ES6 Arrow Functions: Arrow functions are a shorter syntax for writing function expressions which uses less characters to create a function introduced in the ES6 standard. While ES6 Arrow functions can be used in the place of standard JS functions in most places, there are some special cases where ES6 functions will not work. For example, normal JS functions define their own this namespace when they are declared, whereas ES6 functions are linked to the this of the scope from which they are called (see here for more). This means that you cannot, for instance, use ES6 arrow functions for Constructor functions.

Iteration: Iteration is the act of repeating a particular block of code either a known ammount of times (think for loops) or an unknown ammount of times where you are waiting for a condition to be met (think while loops). Very often, we iterate over reference type variables to access and work with each value contained within them.

Iterator: An Iterator is a type of object that allows for iteration over it's elements and often provides special methods that can be used for common iteration tasks. Arrays and Objects are both examples of iterator objects.

Higher-order Function: A higher order function is any function that takes one or more other functions as input arguments. Methods for iterating providing by iterator objects are commonly higher-order functions.

Predicate Functions: Functions that return either true or false.

Immediately Invoked Function: An immediately invoked functions is an anonymous function that is wrapped in parentheses, which runs the functions as soon as it is declared.

NOTES

  • All iteration methods of the Array (which is itself an iterator object), are first-class functions which take a function as their argument. It is often easiest as far as readability to use an ES6 arrow function for the argument.

  • Javascript has generously populated with all of those useful iteration methods in Array by putting them in Array.prototype. Whenever you create a new array, Javascript actual runs the built-in Array constructor, which gives the array access to these methods.

  • Choosing forEach vs map methods to iterate over an Array should be done with care. forEach is used when you want to iterate over all of the elements contained within an array and do something with each of those values. When you use map, you are trying to take your array of lengthn and return another array of length n, ie you are transforming each value in the array to a new value using some calculation.

EXAMPLES

Immediately Invoked Functions

  • anonymous functions cannot be called later if they are not assigned to a variable name

  • function (foo, bar) {
        const sum = foo + bar
        return foo + bar
    }
    
    // once declared, we can no longer access this
    // function because it doesn't have a name!
  • you can use immediately invoked functions to defined anonmyous functions and run them immidietly. This is useful when you want a function to run exactly once (ie not intended for reuse):

  • // to invoke a function immediately, you surround it // with parentheses which runs it, and you pass it 
    // arguments within the standard invocation
    // parentheses
    
    (function (foo, bar) {
        const sum = foo + bar
        return foo + bar
    }(3,4)
    // RETURNS:
    // 7

How Arrow Functions are Useful

  • standard function expression:

  • const myFunction = function(foo, bar) {
        const sum = foo + bar
        return sum
    }
    
    myFunction(3, 4)
    // RETURNS:
    // 7
  • ES6 arrow function expression:

  • const myFunction = (foo, bar) => {
        const sum = foo + bar
        return sum
    }
    
    myFunction(3, 4)
    // RETURNS:
    // 7
  • ES6 arrow functions with only one line in function block:

  • // since there is only one line in the function 
    // block, ES6 arrow functions allow us to remove the 
    // curly braces and remove the return keyword and 
    // put it in one line
    const myFunction = (foo, bar) => {
      return foo + bar
    }
    
    // refactored to:
    const myFunction = (foo, bar) => foo + bar
  • standard single argument function expression vs ES6 single argument function expression

  • // standard function expression
    const myFunction = function(foo) {
        return foo + 1
    }
    
    // ES6 arrow function expression
    
    // arrow functions allow you to remove parentheses
    // around the function parameters if ther is only
    // one parameter
    const myFunction = (foo) => foo + 1
    
    // refactored to:
    const myFunction = foo => foo + 1

Breaking Down an Array Iteration Method

  • let's take a look at map. First we create an array:

  • // how we normally make an array
    const students = ['Kelechi', 'River', 'Kimber']
    
    // equivalent to this constructor function 
    // instantiation
    const students = new Array('Kelechi', 'River', 'Kimber')
  • what methods are available to this array? Let's check out Array.prototype:

  • console.log(Array.prototype)
    
    // RETURNS:
    // [
    // concat(): f concat()
    // constructor: ƒ Array()
    // copyWithin: ƒ copyWithin()
    // entries: ƒ entries()
    // every: ƒ every()
    // fill: ƒ fill()
    // filter: ƒ filter()
    // find: ƒ find()
    // findIndex: ƒ findIndex()
    // forEach: ƒ forEach()
    // includes: ƒ includes()
    // indexOf: ƒ indexOf()
    // ...
    // ]
    
  • wow, tons of methods! Let's try and use map and break it down into it's parts:

    // will take in text and return it uppercase with
    // an exclamation at the end
    const shout = text => `${text.toUpperCase()}!`
    
    students.map(shout)
    // RETURNS:
    // [ 'KELECHI!', 'RIVER!', 'KIMBER!' ]
    • students is the Array instance
      • it is an iterator object
      • it inherits iteration methjods from Array.prototype
    • map is an iterator method that belongs to students
      • map takes a function as an argument, therefore map is a higher-order function
      • the reason we can even pass functions as arguments at all is because JS functions are first-class objects
      • map provides each element of students to shout one by one, returning the resulting value for running shout on that element to a new array
    • shout is a simple ES6 arrow function that is passed to map
      • since shout is passed to map as an argument, it is a kind of callback method
      • notice how shout is only concerned with transforming one element at a time, wheras map automatically will pipe each value of student one-by-one into shout and collect the returned values
  • we can make the code above shorter. Here's where ES6 arrow functions and their compactness really shine:

  • // instead of making a separate function called 
    // shout as below ...
    const shout = text => `${text.toUpperCase()}!`
    students.map(shout)
    
    // ... we can take the guts of shout and pass it 
    // into students in one line, as an anonymous
    // function
    students.map(text => `${text.toUpperCase()}!`)

Lab Code

Here is the code we used today while going over the Lab.

  • bin/for-each.js

  • #!/usr/bin/env node
    'use strict'
    
    // Example array
    const nums = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
    
    // 1.  Find the sum of all elements in an array using named arrow function
    
    // CODE ALONG CODE GOES HERE
    
    // OLD SCHOOL WAY OF DOING THIS WITHOUT REDUCE
    let accumulator = 0
    
    for (let i = 0; i < nums.length; i++) {
      accumulator = accumulator + nums[i]
    }
    
    console.log(accumulator)
    
    // USING REDUCE INSTEAD
    const reducer = (accumulator, currentVal) => accumulator + currentVal
    const sum = nums.reduce(reducer)
    console.log(sum)
    
    // USING REDUCE WITHOUT DECLARING A SEPARATE NAMED FUNCTION
    // notice that the names of the parameters for the reduce callback
    // can be whatever you want to call them (compare this code to the
    // previous section's code)
    sum = nums.reduce((prev, curr) => prev + curr)
    console.log(sum)
    
    // 2.  Find the largest of all elements in an array using named arrow function
    
    // CODE ALONG CODE GOES HERE
    
    const largest = nums.reduce((prev, curr) => prev > curr ? prev : curr)
    console.log(largest)
    
    // 3.  Find the total number of days in fridge for all the food in the fridge
    // using anonymous arrow function
    // start the count with 0
    
    const fridge = [
        { food: 'Carrots', daysInFridge: 32 },
        { food: 'Onions', daysInFridge: 23 },
        { food: 'Bell Peppers', daysInFridge: 16 },
        { food: 'Soda', daysInFridge: 7 },
        { food: 'Pizza', daysInFridge: 4 },
        { food: 'Cake', daysInFridge: 3 }
    ]
    
    // CODE ALONG CODE GOES HERE
    
    const howLazyYouAre = (prev, curr) => {
      const numDays = curr.daysInFridge
      return prev + numDays
    }
    
    fridge.reduce(howLazyYouAre, 0)
  • bin/map.js

  • #!/usr/bin/env node
    'use strict'
    
    // Starting array
    const developers = ['Mike', 'Toni', 'Jessica']
    
    // Iterate using FOR loop to create an array of 'Hello <name>' for each student
    // Original array unchanged
    let developerGreetings = []
    for (let i = 0; i < developers.length; i++) {
      developerGreetings.push('Hello ' + developers[i])
    }
    
    // Iterate using .forEach to create an array of 'Hello <name>' for each student
    // Original array unchanged
    // note: forEach returns undefined
    developerGreetings = []
    developers.forEach(developer => developerGreetings.push('Hello ' + developer))
    
    // example of above code using standard JS function
    developers.forEach(function(developer) {
      developerGreetings.push('Hello ' + developer)
    })
    
    // 1.  Iterate using .map to create an array of 'Hello <name>' for each student
    // Original array unchanged
    // CODE ALONG CODE GOES HERE
    
    developerGreetings = developers.map(developer => `Hello ${developer}`)
  • bin/reduce.js

  • #!/usr/bin/env node
    'use strict'
    
    // Example array
    const nums = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
    
    // 1.  Find the sum of all elements in an array using named arrow function
    
    // CODE ALONG CODE GOES HERE
    
    // OLD SCHOOL WAY OF DOING THIS WITHOUT REDUCE
    let accumulator = 0
    
    for (let i = 0; i < nums.length; i++) {
      accumulator = accumulator + nums[i]
    }
    
    console.log(accumulator)
    
    // USING REDUCE INSTEAD
    const reducer = (accumulator, currentVal) => accumulator + currentVal
    const sum = nums.reduce(reducer)
    console.log(sum)
    
    // USING REDUCE WITHOUT DECLARING A SEPARATE NAMED FUNCTION
    // notice that the names of the parameters for the reduce callback
    // can be whatever you want to call them (compare this code to the
    // previous section's code)
    sum = nums.reduce((prev, curr) => prev + curr)
    console.log(sum)
    
    // 2.  Find the largest of all elements in an array using named arrow function
    
    // CODE ALONG CODE GOES HERE
    
    const largest = nums.reduce((prev, curr) => prev > curr ? prev : curr)
    console.log(largest)
    
    // 3.  Find the total number of days in fridge for all the food in the fridge
    // using anonymous arrow function
    // start the count with 0
    
    const fridge = [
        { food: 'Carrots', daysInFridge: 32 },
        { food: 'Onions', daysInFridge: 23 },
        { food: 'Bell Peppers', daysInFridge: 16 },
        { food: 'Soda', daysInFridge: 7 },
        { food: 'Pizza', daysInFridge: 4 },
        { food: 'Cake', daysInFridge: 3 }
    ]
    
    // CODE ALONG CODE GOES HERE
    
    const howLazyYouAre = (prev, curr) => {
      const numDays = curr.daysInFridge
      return prev + numDays
    }
    
    fridge.reduce(howLazyYouAre, 0)