Giter VIP home page Giter VIP logo

js-functions-ins-and-outs's Introduction

General Assembly Logo

JavaScript Functions - "Ins & Outs"

Prerequisites

Objectives

By the end of this talk, developers should be able to:

  • Use block scope to identify which variables are accessible in a function
  • Create and invoke functions that take an arbitrary number of arguments
  • Create and invoke functions that take reference types as arguments
  • Create and invoke functions that return reference types
  • Create and invoke functions that take functions as arguments
  • Create and invoke functions that return functions

Preparation

  1. Fork and clone this repository.
  2. Create a new branch, training, for your work.
  3. Install dependencies with npm install.

Introduction

JavaScript function argument and return values

"Ins & Outs"

"Ins"

Block scope

Scope refers to where variables and functions are accessible.

Demo - global and local scope

Block scope means our different scopes are defined by blocks { }.

// I am not inside a block
if (true) {
  // i am inside a block
}
// I am not inside a block

NOT objects but blocks.

if (true) {
  // i am inside a block
}

let obj = {
  prop1: "I am not inside a block",
  prop2: "This is an object silly"
}

The outer most scope is the global scope and all inner scopes are considered local scopes.

// global scope
if (true) {
  // local scope
}
// global scope

Variables are accessible within the scope they are declared.

// global scope
if (true) {
  // local scope
  let x = 1  // what would happen if `var` were used instead?
  console.log(x)  // 1
  // When should we use `console` functions?
}
// global scope
console.log(x)  // ReferenceError: x is not defined

They are accessible to any inner scopes (child scopes).

// global scope
let x = 1

if (true) {
  // local scope
  x = 2
  console.log(x)  // 2
}
// global scope
console.log(x)  // 2

But not to the scopes above them (parent scopes).

// global scope
let x = 1

if (true) {
  // local scope
  let y = x
  console.log(y)  // 1
}
// global scope
console.log(x)  // 1
console.log(y)  // ReferenceError: y is not defined

Variables are not accessible from sibling scopes.

if (true) {
  // local scope of 1st sibling
  let a = 1
  console.log(a) // 1
}

if (true) {
  // local scope of 2nd sibling
  console.log(a) // ReferenceError: a is not defined
}

Different scopes can have variables that are declared with the same name and they do not conflict or know about each other.

// global scope
const x = 1
console.log(x)  // 1

if (true) {
  // local scope
  const x = 2
  console.log(x)  // 2
}
// global scope
console.log(x)  // 1

So that means a variable declared in the global scope is accessible by all of the scopes we create and a variable declared in a local scope is only accessible to itself and its child scopes.

Code Along - debugging variable scope
// global scope
let a = 1

if (true) {
  // local scope of 1st nested if statement
  let b = 2

  if (true) {
    // local scope of 2nd nested if statement
    let c = 3
    console.log(a) // 1
    console.log(b) // 2
    console.log(c) // 3
  }

  // local scope of 1st nested if statement
  console.log(a) // 1
  console.log(b) // 2
  console.log(c) // ReferenceError: c is not defined
}

// global scope
console.log(a) // 1
console.log(b) // ReferenceError: b is not defined
console.log(c) // ReferenceError: c is not defined

Conditions are just 1 example of block scope. Loops are another example of block scope.

while (true) { // don't run this
  let a = 1
  console.log(a) // 1
}
console.log(a) // ReferenceError: a is not defined

For Loops still have block scope even though the syntax is different.

for (let i = 1; i < 2; i++) {
  console.log(i) // 1
}
console.log(i) // ReferenceError: i is not defined

Functions are another example of block scope.

const anyFunction = function() {
  let a = 1
  console.log(a) // 1
}

console.log(a) // ReferenceError: a is not defined

The scope of our parameters are within the function block as well

const print = function(a) {
  console.log(a)
}

print(1) // 1
console.log(a) // ReferenceError: a is not defined

Functions with 0 arguments

Some functions do not have parameters when they are defined and do not need to be passed arguments when they are called.

const printHello = function(){
  console.log("Hello World")
}

printHello()

Functions with 1 or more arguments

Some functions define 1 or more parameters and expect 1 or more arguments to be passed when called.

const subtract = function(num1, num2){
  return num1 - num2
}

subtract(2, 1) // 1

The order of the arguments matter.

const subtract = function(num1, num2){
  return num1 - num2
}

subtract(1, 2) // -1
subtract(2, 1) // 1

The type of the arguments matter.

const add = function(num1, num2){
  return num1 + num2
}

add(1, 2) // 3
add("cat", 1) // "cat1"

It is up to the developer to know the order and type of arguments a function is expecting.

The arguments passed to a function can be any primitive data types or objects which include objects, arrays, and functions.

// array
const subtract = function(nums){
  return nums[0] - nums[1]
}

// number
const add = function(num1, num2){
  return num1 - num2
}

subtract( [2, 1] ) // 1
add( 2, 1 ) // 3

In Javascript a function can accept an unlimited number of arguments since every function has an arguments object that is a mechanism to handle arguments not in the function definition. This object is referred to as array like and is available within any function. We'll examine how this object is used by creating some seemingly parameterless functions.

Demo - arguments
const print = function () {
  console.log(arguments[0])
}

print() // undefined
print("cat") // "cat"
print(100, 200) // 100
Code along - arguments
// takes an arbitrary number of arguments (each arg
// should be a number), finds the largest one, and
// returns that member

const max = function () {

}

Could we accomplish something similar using a single argument?

Lab - single array argument

Write a function maxOfArray that takes an array of numbers and returns the max.

Reference types as arguments

Reference types passed as arguments can be modified within the functions.

Demo - primitive data types as arguments
let num = 1

const change = function (num) {
  num++
  console.log(num)
}

change(num) // 2
console.log(num) // 1
Demo - reference types as arguments - arrays
let numbers = [1, 2, 3]

const change = function (numbers) {
  numbers.push(4)
  console.log(numbers)
}

change(numbers) // [1, 2, 3, 4]
console.log(numbers) // [1, 2, 3, 4]
Demo - reference types as arguments - objects
let person = {
  name: "Mike",
  age: 100
}

const getOlder = function (person) {
  person.age++
  console.log(person.age)
}

getOlder(person) // 101
console.log(person.age) // 101
Code along - reference type arguments
const addProperty = function addProperty(obj, prop, val) {
  // this function takes an object and adds a property
  // to it

}

Functions as arguments

Functions are valid arguments. A function that is passed to another function is called a callback.

const add = function (num1, num2){
  return num1 + num2
}

const subtract = function (num1, num2){
  return num1 - num2
}

const doMath = function (num1, num2, operation) {
  return operation(num1, num2)
}

doMath(2,1, add) // 3
doMath(2,1, subtract) // 1

What is a callback? A callback is a function that is passed to another function.

"Outs"

Primitive data types as returns values

Primitive data types returned are a new instance of the data type

let num = 1

const increase = function (num) {
  num++
  return num
}

let newNum = change(num)
console.log(newNum) // 2
console.log(num) // 1

Reference types as returns values

Reference types declared within the function that are returned from functions create new instances of that reference type.

const createArray = function () {
  let result = []

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

  return result
}

let outcome = createArray(1,2,false,true)
console.log(outcome) // [1, 2, false, true]
console.log(result) // ReferenceError: result is not defined

Reference types not declared within the function that are returned from functions are still the same reference type and not new instances.

let numbers = [1, 2, 3]

const change = function (numbers) {
  numbers.push(4)
  return numbers
}

let newNumbers = change(numbers)
console.log(newNumbers) // [1, 2, 3, 4]
console.log(numbers) // [1, 2, 3, 4]

newNumbers.push(5,6,7)
console.log(newNumbers) // [1, 2, 3, 4, 5, 6, 7]
console.log(numbers) // [1, 2, 3, 4, 5, 6, 7]
Lab - reference types as arguments and return values

Write a function that takes an array of developers and a callback function Loops through the developers to check if they cheated and if they did then applies the correct callback function to adjust their score.

const developer = {
  name: "Mike",
  late: true,
  score: 100
}

const anotherDeveloper = {
  name: "Bernard",
  late: false,
  score: 90
}

const developers = [developer, anotherDeveloper]

const deductForCheating = function (developer) {
  developer.score = 0
}

// write a callback that can be passed to runLateScript
// it should have a parameter for a developer object
// to note the late submission was early in the course
const firstWeek = function () {
}

// the function should accept an array of developers
// and two callback functions
const runLateScript = function () {
  // loop through the developers array and check who was late
  // then pass them as an argument to the correct callback

}

// the function should get passed an array of developers
// and two callback functions
runLateScript()
Code along - return new objects
const createPerson = function (givenName, surname, bornOn, height, weight, eyeColor) {

}

Functions as returns values

Functions returned from functions generate a closure. Closures provide great utility.

Demo - return new functions
const memoFactory = function (memo) {
  let rememberMe = memo
  return function () {
    console.log(rememberMe)
  }
}

let memoOne = memofactory("Hello World")

memoOne() // "Hello World"
Code along - return new functions

Functions returned from functions generate a closure. Closures provide great utility.

const counterFactory = function(count) {

}

Combine the last two concepts and we can have a counting list of memos.

const memoFactory = function (memo) {
  let total = 0

  return function () {
    total+= 1
    return total + ": " + memo
  }
}

const memo = memoFactory()

const entryMonday = memo("Monday was fun")
const entryTuesday = memo("I liked Tuesday")
const entryWednesday = memo("Ugh Wednesday")

console.log(entryMonday) // "1: Monday was fun"
console.log(entryTuesday) // "2: I liked Tuesday"
console.log(entryWednesday) // "3: Ugh Wednesday"

Additional Resources

  1. All content is licensed under a CCยญBYยญNCยญSA 4.0 license.
  2. All software code is licensed under GNU GPLv3. For commercial use or alternative licensing, please contact [email protected].

js-functions-ins-and-outs's People

Contributors

jrhorn424 avatar micfin avatar payne-chris-r avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

js-functions-ins-and-outs's Issues

Some developers confuse "callback" with "method that takes a callback"

This indicates that sometimes when we receive vague feedback about "understanding callbacks", some developers do not properly have the vocabulary in their mind. A visual diagramming of an example might help (like diagramming a sentence in English).

For example, when a developer says "the reduce callback" what they typically mean is "the reduce method", but what experienced developers would hear is "the function the reduce method receives as the first argument".

That confusion makes it impossible to explain what a callback is until the more experienced developer recognizes the mistake.

[1,2,3].reduce((a, b) => { return a + b; });
//        ^---- referred to as callback, therefor:
//        when we say callbacks are "arguments to functions" they get confused

Maintain code in one place

For demos, code should be linked to in the README (either a script or lib), unless that code is intended to be run in a REPL, in which case it is fine as a fenced block. Do not put it in both places.

In a code-along, starter code should be provided on the master branch. Code should be stored in a file on the solution branch, and the consultant can have that branch open while presenting to walk developers through the code-along.

In a lab, starter code should be provided on the master branch. A solution should be provided on the solution branch.

Replace `unlimited` with `arbitrary`

Replace unlimited with arbitrary.

- In Javascript a function can accept an unlimited number of arguments since every function has an arguments object that is a mechanism to handle arguments not in the function definition. 
+ In Javascript a function can accept an arbitrary number of arguments since every function has an arguments object that is a mechanism to handle arguments not in the function definition. 

https://github.com/ga-wdi-boston/js-functions-ins-and-outs#functions-with-1-or-more-arguments

Call back example should be...?

values implies we expect an array as an argument (which we do later on in arrayTransform), recommending changing it to value

The memo example is wrong, or I don't understand the intent. Help?

See annotations for questions

const memoFactory = function (memo) {
  let total = 0
  // notice the lack of a local variable here for closure, as well as the lack of a parameter in the
  // below, returned function
  return function () {
    total+= 1
    return total + ": " + memo // where should this be? Is it defined?
  }
}

const memo = memoFactory() // looks like memo isn't defined

 // looks like we're passing an argument to a generated function that names no parameters
const entryMonday = memo("Monday was fun")
const entryTuesday = memo("I liked Tuesday") // ditto
const entryWednesday = memo("Ugh Wednesday") // ditto

console.log(entryMonday) // "1: Monday was fun" // no, what is actually produced is "1: undefined"
console.log(entryTuesday) // "2: I liked Tuesday" // no, what is actually produced is "2: undefined"
console.log(entryWednesday) // "3: Ugh Wednesday" // and so on

PVD Thoughts (Did not deliver)

I didn't teach this lesson at all. I felt that what was covered here had already been/will be covered in past/future lessons. I think the only thing that isn't/won't be covered in other lessons is the arguments object but I didn't think that was pertinent enough to warrant having to teach the students in person. I actually didn't know about that myself, so super cool to learn!

That said, we did give this lesson to students and the study as well. We told them to go through these on their own time and informed them that they will have a diagnostic on this Monday morning. I personally don't think they should have a diagnostic on this, but my team disagreed and I was OK with that.

Instead, I delivered this lesson on CSS: https://github.com/ga-wdi-lessons/css-review. It went really well. They were especially impressed with how they can change HTML and CSS with the inspector. I think this is going to set them up well for the DOM lesson.

I also had them do this lesson: https://github.com/ga-wdi-lessons/html-intro on their own prior to the CSS class.

As a preview of next week, we plan to cover layout, DOM and jquery, events and callbacks, scope and context, and es6 features. The plan is to get into APIs and AJAX right after Thanksgiving, but before they start project 1. We will make sure that the team that remains is set up for success on delivering that.

Students were really stuck on partial application

Students were really stuck on partial application, even though the code-along was framed as a focus on a function returning another function. Is there another example we could use that doesn't rely on two parameters partially applied? Maybe a static function returned?

Not able to finish with virtual property example.

change function syntax

I think setting it up like this will cause great confusion:

const product = function product() {

};

Should be changed to:

const product = function () {
};

Honest Lab is too negative. We need a better example.

@jrhorn424 would like us to come up with a more pleasant example than Developers Cheating.

https://github.com/ga-wdi-boston/js-functions-ins-and-outs/blob/master/lib/school_honesty_lab.js

Potential replacement but new ideas welcome, just created on the fly.

'use strict'

// person one
const personOne = {
  name: 'Mike',
  hungry: true,
  food: []
}

// person two
const personTwo = {
  name: 'Bernard',
  hungry: false,
  food: []
}

// people array
const people = [personOne, personTwo]

// function that adds food if person is hungry and makes them not hungry
const eat = function (person) {
  person.food.push("Cake")
  person.hungry = false
}

// function that removes food if person is not hungry and makes them hungry
const digest = function (person) {
  person.food.unshift()
  person.hungry = true
}

// the function should accept an array of developers and two callback functions
const runMealScript = function (arrayPeople, callBackEat, callBackDigest) {
  // loop through the students array and check who is hungry
  for(let i = 0; i < arrayPeople.length; i++){
    // if they are hungry or not 
    // then pass them as an argument to the correct callback 
    if (arrayPeople[i].hungry === true ){
       callBackEat(arrayPeople[i]) 
    } else {
       callBackDigest(arrayPeople[i]) 
    }       
  }
}

// the function should get passed an array of people
// and two callback functions
runMealScript(people, eat, digest)

more clear definition of the different types of functions?

const sum = function (first, second) {
  return first + second
}

const sum = (first, second) => {
  return first + second
}

const sum = (first, second) => first + second

const addOne = num => num + 1

Show the different types and talk about the differences

Annotate use of `num` as variable and as parameter

Reference types as arguments

Reference types passed as arguments can be modified within the functions.

Demo - primitive data types as arguments

let num = 1

const change = function (num) {
  num++
  console.log(num)
}

change(num) // 2
console.log(num) // 1

This was causing some confusion as to when num was the global variable and when it was the parameter

Add scope to learning objectives, and add content about scope

A lot of this lesson would make more sense if students had a basic understanding of what scope is. I remember my cohort (009) having a lesson on scope, but it doesn't seem to be included now. I think adding a basic intro to scope in a study or as part of this lesson would be very helpful.

Tom's callback explanation

var operation = function(add, num1, num2) {
  var result = add(num1, num2);
  return result;
}

var add = function add(n1, n2) {
  var result = n1 + n2;
  result result;
};

var answer = operation(add, num1, num2);

Code walk through, each step explicitly.

The change to from add to callback confused.

global scope also confusing.

change operation to

function(cb, str1) {
  var result  = cb(str1);
  return result;
}

operation('Hello', Array.protoype.toLowerCase);

README code is double wrong

(per @gaand)
For the reference type arguments demo

// Write a function that takes an array full of integers, doubles each value, and
// returns a new array with those values.
const arrayTimes2 = function arrayTimes2() {
  let result = [];

  for (let i = 0; i < arguments[0].length; i++) {
    result[i] = arguments[0][i] * 2;
  }

  return result;
};

Solution Branch needs to mirror Master

The solution branch README.md needs to mirror the master branch README.md, and needs to include solutions for the master branch code. I now see that there's additional code merged into the solution branch and it intends to include a big section on scope.

Here's an open PR for discussion on the content in the solution branch: #33. While this topic is being discussed, we should have the solution branch contain the solution code that mirrors the current master branch.

Also discussed in this issue, with solution code dump from @jrhorn424: #17

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.