JavaScript Fundamentals:
Underscore.js
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
Who are you?
- Have a good understanding of
JS arrays, objects, and loops. - Have a basic understanding of
JS functions. - Want to solidify fundamentals
- Seek more practice
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
Higher-Order
Functions
and Callbacks
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
Context
Why do we care about higher order functions and callbacks?
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
So that we can write more declarative and expressive code
// declarative style
var add10 = function(num) {
console.log(num + 10);
};
var nums = [1,2,3]
nums.forEach(add10);
// 11, 12, 13
// imperative style
var nums = [1,2,3];
for (var i=0; i<nums.length; i++) {
console.log(nums[i] + 10);
}
// 11, 12, 13
Which is more clear to you?
Functions Review
What is a function?
1. A block of code
2. We get to determine when this code is run (invoked)
3. Directions for doing something we have created but not executed yet (figuring out driving directions vs. actually driving there; writing down a recipe vs. actually cooking it).
This seems super basic, but thinking of functions this way will make higher order functions a lot easier.
A function is just a block of code, and we get to decide when it is run.
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
1. Take a function as an input (argument)
Higher-Order Functions
var count = 1;
setInterval(function(){
console.log('I am', count++, 'seconds old now');
}, 1000);
2. Return a function as the output
var add = function(num){
var num1 = num;
var addToNum1 = function(num2){
return num1 + num2;
};
return addToNum1;
};
If a function does at least one of the following two things, then it is a baller higher-order function.
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
Higher-Order Functions
In JavaScript...
"higher-order" functions can exist because
JS treats functions as "first-class objects".
In other words...
functions can be:
- created (defined)
- stored (into variables)
- passed (as arguments)
- returned (by functions)
...just like any other object in JS
(just like numbers, strings, booleans, arrays, etc).
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
Callbacks
// higher order function
var ifElse = function(condition, isTrue, isFalse){
if(condition){
// callback function
isTrue();
} else {
// callback function
isFalse();
}
};
var logTrue = function(){ console.log(true); };
var logFalse = function(){ console.log(false); };
ifElse(true, logTrue, logFalse);
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
Callbacks are functions that you pass and invoke inside of higher order functions.
Callbacks: Anonymous functions
Remember from Week 1 that we had two main ways of creating a function?
//Anonymous function saved into a variable
var nameCreator = function (firstName, lastName) {
return firstName + ' ' + lastName
};
//named function
function nameImprover(firstName, lastName) {
return firstName + ' ' + lastName
}
//both work!
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
Callbacks
What if we didn't store the anonymous function into a variable? What if we just left it as is, a set of instructions we've created but not executed yet?
//Anonymous function
function (firstName, lastName) {
return firstName + ' ' + lastName
};
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
Callbacks
var ifElse = function(condition, isTrue, isFalse){
if(condition){
isTrue();
} else {
isFalse();
}
};
ifElse(true,
function(){ console.log(true); },
function(){ console.log(false); }
);
Let's refactor our code to just use anonymous functions, instead of declaring them in a separate part of our code and saving them into variables.
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
var ifElse = function(condition, isTrue, isFalse){
if(condition){
isTrue();
} else {
isFalse();
}
};
ifElse(true,
function(){ console.log(true); }, // this was logTrue()
function(){ console.log(false); }// this was logFalse()
);
Callbacks
var ifElse = function(condition, isTrue, isFalse){
if(condition){
isTrue();
} else {
isFalse();
}
};
ifElse(true,
function(){ console.log(true); },
function(){ console.log(false); }
);
This is a super common pattern in functional programming: to declare anonymous functions in-line as arguments.
Remember, a function is just a block of code we've defined but not run yet. If we're not using this code elsewhere in our program, there's no need to give it a name.
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
Passing Arguments
var ifElse = function(condition, isTrue, isFalse){
if(condition){
isTrue(); // no arguments
} else {
isFalse(); // no arguments
}
};
var ifElse = function(condition, isTrue, isFalse, arg){
if(condition){
isTrue(arg); // Look! An argument! Whoa.
} else {
isFalse(arg); // <(^.^<) OMG it's another one.
}
};
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
var ifElse = function(condition, isTrue, isFalse){
if(condition){
isTrue(); // no arguments
} else {
isFalse(); // no arguments
}
};
var ifElse = function(condition, isTrue, isFalse, arg){
if(condition){
isTrue(arg); // Look! An argument! Whoa.
} else {
isFalse(arg); // <(^.^<) OMG it's another one.
}
};
Passing Arguments
Or, if our higher order function will be giving us the arguments, we can just include those as parameters for our anonymous functions.
When would this happen? You can think of a higher-order function that might iterate through an array, and pass each item in the array to the callback function we pass in. In this case, we're not directly specifying the argument, we're letting the higher-order function give it to us each time.
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
Passing Arguments
var increment = function(n){
return n + 1;
};
var square = function(n){
return n*n;
};
var doMath = function(n, func){
return func(n);
};
doMath(5, square);
doMath(4, increment);
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
Where else are we going to use callbacks?
1. API requests (Get data from Yelp, and once you have that data some number of milliseconds later, invoke this function which is the code I've programmed to play with the Yelp data).
2. Event handlers- Whenever a user clicks on this square, do these things.
3. Functional programming! Next week, I promise :)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
Key takeaways
- A higher order function is a function that takes a function as input and/or returns a function as output
- "Callback" is a term used for any function that is passed as an argument to a function
- they can be named or anonymous
- arguments for callbacks can be passed as arguments to the higher order function
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
Questions
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
Exercises
github.com/telegraphPrep/week-3-introToHigherOrderFunctions
New partners!
(again)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
Underscore.js
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
Context
What we'll do today...
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
Concepts we'll cover:
- _.each
- _.map
- _.reduce
Bring together all of the concepts we've learned to build handy functions using the underscore.js library.
underscore.js
What is it?
A popular library with many useful functional programming methods built in.
Where is it?
http://underscorejs.org
Annotated Source:
http://underscorejs.org/docs/underscore.html
Let's make some of the methods from scratch!
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
//_ is just an empty object that we put methods on
var _ = {};
//_.each is just a property of that object
//that property is set equal to a function
//that function has two parameters
_.each = function(list, callback) {
//function body here
};
//when you load up the underscorejs library
//all you're doing is loading an enormous object
//that has 200+ properties that are functions
Using the underscorejs library
What is this _ object that I'm invoking methods on?
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
_.each() usage
var pocketmons = ['Charisaur', 'Bulbazard', 'Twomew'];
var logger = function(val){
console.log(val);
};
_.each(pocketmons, logger);
//'Charisaur'
//'Bulbazard'
//'Twomew'
//_.each(list, iterator)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
_.each() usage
- Iterates over a list of elements, giving them one at a time to an iterator function.
- Each invocation of iterator is called with three arguments: element, index, list. If list is an Object, iterator's arguments will be value, key, list.
Each is just a fancy for loop that underscore provides for us.
var each = function(list, iterator) {
//function body here to make each work
};
//Example invocation:
_.each(pocketmons, logger);
//'Charisaur'
//'Bulbazard'
//'Twomew'
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
http://underscorejs.org/#each
- Iterates over a list of elements, giving them one at a time to an iterator function.
- Each invocation of iterator is called with three arguments: value, index, list. If list is a JavaScript object, iterator's arguments will be value, key, list.
//PSEUDOCODE!!
//declare a function that has two parameters
//determine if collection is an array or an object
//loop through the collection
//invoke the callback on each element in the collection
_.EACH() DEFINED
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
http://underscorejs.org/#each
- Iterates over a list of elements, giving them one at a time to an iterator function.
var _ = {};
//declare a function that has two parameters
_.each = function(list, callback) {
//determine if collection is an array or an object
//loop through the collection
//invoke the callback on each element in the collection
};
_.EACH() DEFINED
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
http://underscorejs.org/#each
- Iterates over a list of elements, giving them one at a time to an iterator function.
var _ = {};
_.each = function(list, callback) {
//determine if list is an array or an object
if(Array.isArray(list)) {
//use array for loop
//invoke the callback on each element in the list
} else {
//use object for loop
//invoke the callback on each element in the list
}
};
_.EACH() DEFINED
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
http://underscorejs.org/#each
- Iterates over a list of elements, giving them one at a time to an iterator function.
var _ = {};
_.each = function(list, callback) {
if(Array.isArray(list)) {
for (var i = 0; i < list.length; i++) {
//invoke the callback on each element in the list
}
} else {
for (var key in list) {
//invoke the callback on each element in the list
}
}
};
_.EACH() DEFINED
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
http://underscorejs.org/#each
- Iterates over a list of elements, giving them one at a time to an iterator function.
var _ = {};
_.each = function(list, callback) {
if(Array.isArray(list)) {
for (var i = 0; i < list.length; i++) {
callback(list[i], i, list);
}
} else {
for (var key in list) {
callback(list[key], key, list);
}
}
};
_.EACH() DEFINED
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
_.each() usage
Which function from myFirstLibrary is _.each equivalent to?
var loopThrough = function(list, callback) {
if(Array.isArray(list)) {
for (var i = 0; i < list.length; i++) {
callback(list[i], i, list);
}
} else {
for (var key in list) {
callback(list[key], key, list);
}
}
};
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
_.EACH with Arrays:
Direct access to element
The callback gets the index and array as well, but don't use them to access the current element.
var names = ['Jeff', 'Preston', 'Bianca'];
function logTwice(name, index, names) {
var currentName = names[index]; // correct
console.log(currentName);
currentName = name; // correct AND easier
console.log(currentName);
}
_.each(names, logTwice);
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
_.EACH with Objects:
Direct access to Property value
The callback gets the key and object as well, but don't use them to access the current property value.
var superheroes = {
batman : 'human',
superman : 'alien',
ironman : 'human',
groot : 'alien',
wolverine : 'mutant'
};
function logNameIfHuman(type, heroName, superheroes) {
var currentType = superheroes[heroName]; // correct
currentType = type; // correct AND easier
if(currentType === 'human') {
console.log(heroName);
}
}
_.each(superheroes, logNameIfHuman);
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
Looping with _.each
// Let's use _.each to solve this problem:
var addTwoToAllElements = function(arr){
_.each(arr, function(val, index, collection){
collection[index] = val + 2;
});
};
var arr = [1, 2, 3, 4, 5];
addTwoToAllElements(arr);
console.log(arr) // [3, 4, 5, 6, 7];
Let's solve a problem using each.
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
// Let's use _.each to solve this problem:
var addTwoToAllElements = function(arr){
_.each(arr, function(val, index, collection){
collection[index] = val + 2;
});
};
var arr = [1, 2, 3, 4, 5];
addTwoToAllElements(arr);
console.log(arr) // [3, 4, 5, 6, 7];
Nested Looping with _.each()
var studentA = {
firstName: 'Ryan',
lastName: 'Gosling'
};
var classA = {
subject: 'JavaScript',
teacher: '@RebootJeff',
students: [ /* studentA, studentB, etc... */ ]
};
var classes = [ /* classA, classB, etc... */ ];
for(var i = 0; i < classes.length; i++) {
for(var j = 0; j < classes[i].students.length; j++) {
var fullName = classes[i].students[j].firstName +
' ' + classes[i].students[j].lastname;
console.log(fullName);
}
}
_.each(classes, function(class) {
_.each(class.students, function(student) {
var fullName = student.firstName + ' ' + student.lastName;
console.log(fullName);
});
});
How do we print all the names
of all the students
of all the classes?
for(var i = 0; i < classes.length; i++) {
var students = classes[i].students; // This improves readability
for(var j = 0; j < students.length; j++) {
var fullName = students[j].firstName + ' ' + students[j].lastname;
console.log(fullName);
}
}
MUCH easier to read:
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
var pocketmon = ['Charisaur', 'Bulbazard', 'Twomew'];
var stokedFunc = function(val){
return val + '!!!';
};
var stokedPocketmon = _.map(pocketmon, stokedFunc);
_.MAP() usage
//_.map(list, iterator)
console.log(stokedPocketmon);
//['Charisaur!!!','Bulbazard!!!','Twomew!!!']
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
_.map() defined
var _ = { each: function(/*...*/) { /*...*/ } };
_.map = function(list, iterator) {
var result = []; // make a new array
_.each(list, function(item, index, list) {
result.push(iterator(item, index, list));
});
return result;
};
- Produces a new array of values by mapping each value in list through a transformation function (iterator).
- Each invocation of iterator is called with three arguments: (element, index, list). If list is a JavaScript object, iterator's arguments will be (value, key, list).
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
_.map() defined
function copyBy = function(list, iterator) {
var result = []; // make a new array
loopThrough(list, function(item, index, list) {
result.push(iterator(item, index, list));
});
return result;
};
Which function from myFirstLibrary is synonymous with _.map?
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
LOOPING WITH _.MAP
function AnimalMaker(name) {
return {
speak: function () {
console.log("my name is ", name);
}
};
};
var animalNames = ['Frog', 'Falcon', 'Fox'];
// Remember coding WITHOUT Underscore?
var farm = [];
for(var i = 0; i < animalNames.length; i++){
farm.push(AnimalMaker(animalNames[i]));
}
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
_.map vs _.each
function AnimalMaker(name) {
return {
speak: function () {
console.log("my name is ", name);
}
};
};
var animalNames = ['Frog', 'Falcon', 'Fox'];
// Mapping builds up an array and returns it.
var farm = _.map(animalNames, function (name) {
return AnimalMaker(name);
});
// An each loop returns nothing.
// Just use it to iterate over an array.
_.each(farm, function (animal) {
animal.speak();
});
I want to simply loop through an array or object.
I want a new array based on an existing one.
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
Key takeaways
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
- Underscore.js is a library that allows us to do a multitude of functionality (some of which we've already build over the last couple of days)
- _.each basically does what a for loop does
- you can't return anything from its callback
- _.map produces a new array
- it's callback requires a return statement
Questions
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
Exercises
https://github.com/TelegraphPrep/week-4-underscoreAlgorithms
![](https://s3.amazonaws.com/media-p.slid.es/uploads/362520/images/1635394/stucked.png)
Underscore.js
By telegraphprep
Underscore.js
An introduction to functional programming
- 1,007