Lab 4: JavaScript Array Methods and Nested Functions
This lab covers workbook experiments 7 and 8. You will practice JavaScript array manipulation methods and learn how nested functions share variables through closure, with the exact expected output shown for every experiment so you can verify your work.
Workbook Alignment
- Experiment 7: Demonstrate built-in array methods
- Experiment 8: Demonstrate nested functions
Learning Objectives
By the end of this lab, you will be able to:
- use common JavaScript array methods
- predict the output of
map(),filter(),reduce(),find(),includes(), andindexOf() - understand function scope and closures
- write nested functions for reusable logic
- display JavaScript output clearly in the browser
Software and Files Required
- completion of Lab 3
- VS Code or any text editor
- a modern browser with developer tools (press F12)
- a folder named
Lab04 - files named
array-methods.htmlandnested-functions.html
Experiment 7: Built-in Array Methods
Problem Statement
Create a JavaScript program that demonstrates built-in array methods: map(), filter(), reduce(), find(), includes(), and indexOf().
Array Methods — Quick Reference
Study this table before writing the code so you know what result to expect from each method:
| Method | What it does | Returns |
|---|---|---|
map(fn) |
Creates a new array by applying fn to every element |
New array, same length as original |
filter(fn) |
Creates a new array keeping only elements where fn returns true |
New array, shorter or equal length |
reduce(fn, start) |
Collapses the array into one value by accumulating results | A single value (number, string, etc.) |
find(fn) |
Returns the first element where fn returns true |
One element, or undefined if nothing matches |
includes(val) |
Checks whether val exists anywhere in the array |
true or false |
indexOf(val) |
Finds the index (position) of val in the array |
A number (0-based), or −1 if not found |
Folder Structure
Lab04/
array-methods.html
nested-functions.html
Procedure
- Create the
Lab04folder. - Add a new file named
array-methods.html. - Declare the array
const numbers = [10, 15, 20, 25, 30]. - Apply each of the six array methods and store the results in variables.
- Build a text report and display it inside a
<pre>element so newlines are preserved. - Open in a browser and compare your output with the expected output below.
Solution Code (array-methods.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lab 4 - Array Methods</title>
</head>
<body>
<h1>Array Methods Demo</h1>
<!-- <pre> preserves newlines so each result appears on its own line -->
<pre id="output"></pre>
<script>
const output = document.getElementById("output");
// Starting array — five numbers in ascending order
const numbers = [10, 15, 20, 25, 30];
// map(): create a new array by multiplying every element by 2
// 10*2=20 15*2=30 20*2=40 25*2=50 30*2=60
const doubled = numbers.map(number => number * 2);
// filter(): keep only elements that are >= 20
// 10 fails 15 fails 20 passes 25 passes 30 passes
const filtered = numbers.filter(number => number >= 20);
// reduce(): add all elements together, starting at 0
// 0 + 10 + 15 + 20 + 25 + 30 = 100
const sum = numbers.reduce((total, number) => total + number, 0);
const report = [
"Original : " + numbers.join(", "),
"map() : " + doubled.join(", "),
"filter() : " + filtered.join(", "),
"reduce() : " + sum,
// find(): return the FIRST element that is greater than 20
// 10 fails 15 fails 20 fails 25 passes — stops here, returns 25
"find() : " + numbers.find(number => number > 20),
// includes(): is the value 25 present in the array? → true
"includes(): " + numbers.includes(25),
// indexOf(): at which index is the value 20?
// index 0=10 index 1=15 index 2=20 — found at position 2
"indexOf() : " + numbers.indexOf(20)
];
output.textContent = report.join("\n");
</script>
</body>
</html>Expected Browser Output
After opening array-methods.html in a browser, the <pre> block should display exactly:
Original : 10, 15, 20, 25, 30
map() : 20, 30, 40, 50, 60
filter() : 20, 25, 30
reduce() : 100
find() : 25
includes(): true
indexOf() : 2
| Method call | Step-by-step calculation | Result |
|---|---|---|
map(n => n * 2) |
10×2, 15×2, 20×2, 25×2, 30×2 | [20, 30, 40, 50, 60] |
filter(n => n >= 20) |
10 ✗ 15 ✗ 20 ✓ 25 ✓ 30 ✓ | [20, 25, 30] |
reduce((t,n) => t+n, 0) |
0+10+15+20+25+30 | 100 |
find(n => n > 20) |
10 ✗ 15 ✗ 20 ✗ 25 ✓ (stops here) | 25 |
includes(25) |
Is 25 in [10,15,20,25,30]? | true |
indexOf(20) |
10 is at 0 15 at 1 20 at 2 | 2 |
map(),filter(), andreduce()do not change the original array. After all six operations,numbersis still[10, 15, 20, 25, 30].indexOf()returns-1— notfalseornull— when the value is not found.find()returnsundefined— not[]ornull— when no element matches the condition.filter()always returns an array even if only one element passes.find()returns a single element, not an array.
Experiment 8: Nested Functions
Problem Statement
Write a JavaScript program using nested functions to generate student reports that show names, marks, and calculated grade letters.
Understanding Nested Functions
A nested function is a function defined inside another function. The key rule is:
An inner function can read and use variables from the outer function that contains it. This access to an outer function’s variables is called closure.
studentReport(name, marks) ← outer function — defines: name, marks
├── calculateGrade() ← inner function — can read: marks
└── buildMessage() ← inner function — can read: name
└── calls calculateGrade()
Both inner functions share the outer function’s name and marks without needing them passed as arguments again.
Procedure
- Create a new file named
nested-functions.html. - Write an outer function
studentReport(name, marks). - Inside it, write an inner function
calculateGrade()that readsmarksfrom the outer scope and returns a letter grade. - Write another inner function
buildMessage()that readsnamefrom the outer scope and callscalculateGrade(). - Return the result of
buildMessage()from the outer function. - Call
studentReport()three times with different names and marks. - Display all three reports and compare with the expected output.
Solution Code (nested-functions.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lab 4 - Nested Functions</title>
</head>
<body>
<h1>Nested Functions Demo</h1>
<pre id="result"></pre>
<script>
// Outer function: receives a student's name and marks as parameters
function studentReport(name, marks) {
// Inner function 1: reads 'marks' from the outer function's scope
function calculateGrade() {
if (marks >= 90) return "A"; // 90 and above
if (marks >= 75) return "B"; // 75 to 89
if (marks >= 60) return "C"; // 60 to 74
return "D"; // below 60
}
// Inner function 2: reads 'name' from the outer scope
// and calls calculateGrade() defined above
function buildMessage() {
const grade = calculateGrade();
return name + " scored " + marks + " and received grade " + grade;
}
// The outer function returns the string built by buildMessage()
return buildMessage();
}
// Call the function three times with different students
const report1 = studentReport("Ravi", 82); // 75–89 → Grade B
const report2 = studentReport("Priya", 91); // ≥ 90 → Grade A
const report3 = studentReport("Arjun", 58); // < 60 → Grade D
document.getElementById("result").textContent =
report1 + "\n" + report2 + "\n" + report3;
</script>
</body>
</html>Expected Browser Output
After opening nested-functions.html, the <pre> block should display exactly:
Ravi scored 82 and received grade B
Priya scored 91 and received grade A
Arjun scored 58 and received grade D
studentReport("Ravi", 82)
| Step | What happens |
|---|---|
| 1 | studentReport("Ravi", 82) is called. Inside, name = "Ravi" and marks = 82. |
| 2 | buildMessage() is called from inside the outer function. |
| 3 | Inside buildMessage(), calculateGrade() is called. |
| 4 | calculateGrade() reads marks (82) from the outer scope. Checks: 82 >= 90? No. 82 >= 75? Yes → returns "B". |
| 5 | buildMessage() builds: "Ravi" + " scored " + 82 + " and received grade " + "B" → returns "Ravi scored 82 and received grade B". |
| 6 | The outer function returns this string. It is stored in report1. |
calculateGrade()andbuildMessage()are helpers that only make sense insidestudentReport(). Keeping them inside hides them from the rest of the script and prevents naming conflicts.- Because all three functions share the same outer scope,
calculateGrade()can readmarksandbuildMessage()can readnamewithout those values being passed again as separate arguments. - This pattern is called encapsulation — grouping related logic so it stays together and does not interfere with other parts of the program.
Observation Questions
- What is the difference between
map()andfilter()? - What does
reduce()return when the initial value is0and the array is[1, 2, 3]? - What would
find()return if no element in the array satisfies the condition? - In Experiment 8, which variables can
calculateGrade()access, and why?
Viva Questions
- What is a closure in JavaScript?
- What is the difference between
find()andfilter()? - What does
indexOf()return when the element is not found in the array? - Can an inner function access variables of the outer function? Explain using an example from this lab.
Submission Checklist
array-methods.htmlnested-functions.html- screenshots showing the exact output matching the expected output above for both experiments
- short answer file for observation and viva questions
Extension Task
Modify array-methods.html to let the user type comma-separated numbers into an <input> text field. Add a Run button that reads the numbers, converts them to an array using split() and map(Number), runs all six methods, and displays the results dynamically without reloading the page.