Functional JavaScript
Joel Ross
Functions
function sayHello(personName){
return "Hello, " + personName;
}
const msg = sayHello("Joel");
console.log(msg); //"Hello Joel"
FUNCTIONS
ARE ALSO
VALUES
Functions are Values
Functions are a type of value (just like number, string, array).
Anywhere you can put an Array, you can put a Function.
They can be assigned as values to other variables.
//assign array to variable
const myArray = ['a','b','c'];
typeof myArray //=> 'object'
const other = myArray;
//access value in other
console.log( other[1] ); //print 'b'
//assign function to variable
function sayHello(name) {
console.log("Hello, "+name);
}
typeof sayHello // 'function'
const other = sayHello;
//prints "Hello, everyone"
other('everyone');
special array ability
special function ability
Function Literals
const array = [1,2,3]; //named variable (not anonymous)
console.log(array); //pass in named var
console.log( [4,5,6] ); //pass in literal/anonymous value
Functions can be written as literal values, also called an anonymous value (values not assigned a name/label).
//named function
function sayHello(person){
console.log("Hello, "+person);
}
//named function
function sayHello(person){
console.log("Hello, "+person);
}
//function literal (anonymous function) - technically invalid
function(person) {
console.log("Hello, "+person);
}
//named function
function sayHello(person){
console.log("Hello, "+person);
}
//function literal (anonymous function) - technically invalid
function(person) {
console.log("Hello, "+person);
}
//function literal (anonymous function, a value)
//assigned to variable
const sayHello = function(person) {
console.log("Hello, "+person);
}
So they can be assigned to properties (values) in Objects.
const obj = {};
const myArray = ['a','b','c'];
//assign array to object
obj.array = myArray;
//access with dot notation
obj.array[0]; //gets 'a'
//assign literal (anonymous value)
obj.otherArray = [1,2,3]
const obj = {}
function sayHello(name) {
console.log("Hello, "+name);
}
//assign function to object
obj.sayHi = sayHello;
//access with dot notation
obj.sayHi('all'); //prints "Hello, all"
//assign literal (anonymous value)
obj.otherFunc = function() {
console.log("Hello world!");
}
this is how you make
"non-static" methods
Functions are Values
Functions are Values
So they can be passed as parameters to other functions!
const myArray = ['a','b','c'];
//takes array as an argument
//will access the arg array
//with an index of 1
function doWithOne(array) {
console.log( array[1] );
}
//call function and pass value
doWithOne(myArray); //prints 'b'
//pass literal (anonymous value)
doWithOne([1,2,3]) //prints '2'
function sayHello(name) {
console.log("Hello, "+name);
}
//takes ANOTHER FUNCTION as an arg
//will call the arg function,
//passing it "world"
function doWithWorld(aFunction) {
aFunction("world");
}
//call function and pass value
doWithWorld(sayHello); //"Hello world"
//pass literal (anonymous value)
doWithWorld(function(msg) {
console.log("you said: "+msg);
}); //prints "you said: world"
/* note where parens and braces close! */
array ability with hard-coded value
function ability with hard-coded value
Passing vs. Calling
When you pass a function as an argument, do not include parentheses after it. Including parentheses calls the function (executes it), and replaces that expression with the returned value.
function sayHello() { //version with no args
return "Hello";
}
//print out the function
console.log( sayHello ); // logs "[Function: sayHello]"
// the function
//resolve the expression, THEN print that out
console.log( sayHello() ); // logs "Hello", which is
// what `sayHello()` resolves to.
Callback Functions
A term for a function that is passed into another function for the receiver to "call back to" and execute later.
//takes in TWO callback functions!
function doTogether(firstCallback, secondCallback){
firstCallback(); //execute the first function
secondCallback(); //execute the second function
console.log('at the "same time"!');
}
function patHead() {
console.log('pat your head');
}
function rubBelly() {
console.log('rub your belly');
}
//pass in the callbacks to do them together
doTogether(patHead, rubBelly);
no parens, not calling now (just passing the variable!)
Using Callbacks
Many built-in functions (as well as library functions) expect callback functions as arguments.
//Arbitrary list of people's names, heights, and weights
const peopleArray = [{name: 'Ada', height: 64, weight: 135},{name: 'Bob', height: 74, weight: 156},{name: 'Chris', height: 69, weight: 139},{name: 'Diya', height: 69, weight: 144},{name: 'Emma', height: 71, weight: 152}]
//a function to "sort" people objects. Returns
// < 0 if A comes before B,
// > 0 if B comes before A
// 0 if A and B stay in current order
function sortByHeightFunction(personA, personB) {
if(personA.height < personB.height) {
return -1; //person A is shorter, so they come first
} else if(personB.height < personA.height) {
return 1; //person B is shorter, so they come first
} else {
return 0;
}
}
peopleArray.sort(sortByHeightFunction); //sorts in place!
We will occasionally write functions that expect callbacks, but we will pass many callbacks to existing functions!
JS: Functional Looping
Joel Ross
Array Iteration
To iterate through each item in an array you can, use
the .forEach() function and pass it a callback to execute on each array item.
This function has a for loop in it already.
//Iterate through an array
const array = ['a','b','c'];
const printItem = function(item) {
console.log(item);
}
array.forEach(printItem);
//more common to use anonymous function literal
array.forEach(function(item) {
console.log(item);
});
callback
Mapping
function square(n) { //a function that squares a number
return n*n;
}
const numbers = [1,2,3,4,5]; //an initial array
//transform the numbers using the square() function
const squares = []; //the transformed array
for(let i=0; i<numbers.length; i++) {
const transformed = square(numbers[i]);
squares.push(transformed); //add transformed to array
}
console.log(squares); // [1, 4, 9, 16, 25]
The .map() function applies the given callback function to each element in an array and returns a new array of the transformed values.
This function has a for loop in it already.
function square(n) { //a function that squares a number
return n*n;
}
const numbers = [1,2,3,4,5]; //an initial array
//map the numbers using the `square` transforming function
const squares = numbers.map(square);
console.log(squares); // [1, 4, 9, 16, 25]
const numbers = [1,2,3,4,5]; //an initial array
//map the numbers using function literal (anonymous callback)
const squares = numbers.map(function(n) {
return n*n;
})
console.log(squares); // [1, 4, 9, 16, 25]
this function does the for loop!
Practice
Define an array peopleNames that contains the names of 3 people (e.g., you and your neighbors).
Use the map() function to create a new array peopleGreetings containing strings "Hi _____!", where the _____ is the name of each person in the peopleNames array.
Filtering
The .filter() function applies the given callback function to each element in an array and returns a new array containing only those elements for which the callback returns true.
This function has a for loop in it already.
const numberArray = [3,1,4,2,5];
const isACrowd = array.filter(function(n) {
return n >= 3; //keep if > 3
}); //returns [3,4,5]
Reducing
The .reduce() function uses the given callback function to aggregate (combine) the elements in the list into a single value. Similar to the summarize() function in R.
function link(accumulation, newItem) { //combines two strings
const newAccumulation = accumulation + "->" + newItem;
return newAccumulation;
}
const letters = ['a','b','c','d','e']; //an initial array
let linked = ""; //an accumulated aggregate, start at ""
for(let i=0; i<letters.length; i++){
linked = link(linked, letters[i]);
}
console.log(linked); //"->a->b->c->d->e"
Reducing
The .reduce() function uses the given callback function to aggregate (combine) the elements in the list into a single value. Similar to the summarize() function in R.
function link(accumulation, newItem) { //combines two strings
const newAccumulation = accumulation + "->" + newItem;
return newAccumulation;
}
const letters = ['a','b','c','d','e']; //an initial array
const linked = letters.reduce(link, ""); //pass func, starting value
console.log(linked); //"->a->b->c->d->e"
Practice
Define an array phoneDigits that is an array of the 7 digits in your phone number (e.g., [8, 6, 7, 5, 3, 0, 9].
Use the reduce() function to get the largest number in this array. Hint: use an if statement in the reducer callback to return the new "current maximum" value seen so far.
map, filter, and reduce
explained with emoji 😂
[🐮, 🥔, 🐔, 🌽].map(cook)
=> [🍔, 🍟, 🍗, 🍿]
[🍔, 🍟, 🍗, 🍿].filter(isVegetarian)
=> [🍟, 🍿]
[🍔, 🍟, 🍗, 🍿].reduce(eat)
=> 💩
💩
info340-functional-javascript
By Joel Ross
info340-functional-javascript
- 235