Functional JavaScript & Interactivity

Joel Ross
Autumn 2026 (B)

View of the Day

  • Quiz 2!

  • JavaScript Q&A

  • Higher Order Functions

  • Event Handling & Interactivity

  • Functional Looping (if time)

Quiz 2

This quiz is closed book, closed note.

Each question is worth 1 point.

Mark your chosen answers clearly, such as by circling
the letter.

You have 20 minutes, good luck!

(reminder to start recording after quiz)

The policy for this course projects:

  • ❌ Don't use AI tools for problem sets
  • ✅ You can use AI tools for projects:
    1. ⚠️ AI can do the "first pass", but you do the debugging part
      • Don't put code into the generator!
    2. ⚠️ You need to distinguish what work is the AI and what work is yours
      • AI-supported code committed separately through git
      • Written explanation of your human work ("project mastery reflection" assignment)

For full details, see the syllabus and the Gen AI in Projects Guidelines

Reminder: AI Policy

JavaScript Q&A

Functions

function sayHello(personName){
    return "Hello, " + personName;
}

const msg = sayHello("Joel");
console.log(msg); //"Hello Joel"

FUNCTIONS

 

ARE ALSO

VALUES

Functions are Values

A function are a type of value (just like number, string, array), and can be used in the same way.

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 (a value 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 getItem1(array) {
  console.log( array[1] );
}



//call function and pass value
getItem1(myArray); //prints 'b'


//pass literal (anonymous value)
getItem1([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 callWithWorld(aFunction) {
   aFunction("world");
}



//call function and pass value
callWithWorld(sayHello); //"Hello world"


//pass literal (anonymous value)
callWithWorld(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 getHello() { //version with no args
    return "Hello";
}

//print out the function
console.log( getHello ); // logs "[Function: getHello]" 
                         // the function

//resolve the expression, THEN print that out
console.log( getHello() ); // logs "Hello", which is 
                           // what `getHello()` 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!

Making Pages Interactive

Event Handling

We add interactivity by listening for and responding to "events" created by the computer.

Register a Listener

Use the addEventListener() function to register a "listener". The function takes 2 arguments: the type of event to listen for (a string), and a callback function to run when the event occurs.

the event that occurred

const button = document.querySelector('button');

button.addEventListener('click', function(event) {

  //what to do when button is pressed!
  console.log("you clicked on", event.target);  

});

which element

cause the event

JS Web App Structure

To develop a web app, think about your page as "displaying dynamic content", not "responding to user actions".

  1. Define the data (state) that your app will be displaying
    • ex: the list of tasks, the current recipe, the user's history
       
  2. Define how to render (display) that data using functions
    • ex: createTaskItem(), renderRecipe() 
       
  3. Define responses to user action. When the user does something:
    1. Update the state data
    2. "re-render" the (now-changed) data!

JS Web App Structure

//define data
const state = {
  data: [ {}, {}, {} ],
  ...
}

//define presentation - lots of these kinds of functions
function renderData() {
  //render all the data
  for(let datum of state.data){
    //call helper functions to break things up!
    const dataCardElement = renderDataCard(datum);
    document.querySelector('#main').appendChild(dataCardElement);
  }
}

//define user interaction
button.addEventListener('click', function(event) {
  state.data[i] = ...; //MODIFY THE STATE
  document.querySelector('#main').innerHTML = ''; //CLEAR OLD VIEW
  renderData(); //RE-RENDER CONTENT    
})

renderData() //show initial content!

Handing Form Data

In order to respond to a form submission, you will need to "stop" the normal HTTP request being sent by calling preventDefault() on the event.

const formElement = document.querySelector('#myForm');

//listen for submit events
formElement.addEventListener('submit', function(event) {
  //stop normal behavior (going to a new site)
  event.preventDefault();

  //access what value the user typed in
  const inputElement = document.querySelector('#name-input')
  const userValue = inputElement.value;
  
  //... do something with that value!  
});

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"

map, filter, and reduce
explained with emoji 😂

[🐮, 🥔, 🐔, 🌽].map(cook)
  => [🍔, 🍟, 🍗, 🍿]

[🍔, 🍟, 🍗, 🍿].filter(isVegetarian)
  => [🍟, 🍿]

[🍔, 🍟, 🍗, 🍿].reduce(eat)
  =>  💩

💩

Action Items!

Action Items!

  • Work on task list for Week 5

  • Read through: Chapter 12

  • Problem Set 05 due Friday

    • ​Can finish it today (probably)

  • Project Draft 1 due Sunday

 

Next: Even more JavaScript (+ work time?)