<info 340/>
Functional JavaScript
Joel Ross
Spring 2024
View of the Day
-
JavaScript Q&A
-
Function Basics
-
Higher Order Functions
-
Callbacks
-
Functional Looping
Today is a syntax day (again)!
JavaScript Q&A
Functions
Functions in JavaScript are like
static
methods in Java
//JavaScript
function greet(greeting, name){
return greeting + ", " + name;
}
const msg = greet("Hello", "World");
//Java
public static String greet(String greeting, String name){
return greeting + ", " + name;
}
public static void main(String[] args){
String msg = greet("Hello", "World");
}
No
access modifier
or return type declared
parameters have no type
parameters are
comma-separated
Call with parens and assign result, like Java
Functions
Functions in JavaScript look like functions in Python, except with C-style blocks (using {})
//JavaScript
function greet(greeting, name){
return greeting + ", " + name;
}
const msg = greet("Hello", "World");
# Python
def greet(greeting, name):
return greeting + ", " + name
msg = greet("Hello", "World")
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 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!
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
forEach() callbacks
When using forEach() to loop through an array, the JavaScript interpreter will call the callback function passing it 3 arguments. (The last two are "optional", since all arguments in JavaScript can be ignored)
//Iterate through an array
const myArray = ['a','b','c'];
myArray.forEach(function(theItem, index, theArray) {
//the item itself (e.g., `array[i]`` in a for loop)
console.log(theItem);
//the index (e.g., `i` in a for loop). Rarely used.
console.log(index);
//the array (e.g., `array` in a for loop). Never used.
console.log(theArray);
});
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)
=> 💩
💩
Action Items!
Action Items!
Read: through Chapter 12
Project Draft 1 due Sunday!!!
-
Problem Set 05 due next Friday
Can focus on the Draft this week/weekend, but don't fall behind!
Next: DOM (bringing it to the web!)
info340sp24-functional-javascript
By Joel Ross
info340sp24-functional-javascript
- 295