Loops and Arrays in JavaScript

Learn to make JavaScript repeat work and handle lists of data. Write for, while and do...while loops that run the right number of times, store values in arrays, and add, remove, search and change their elements. Process lists with for...of and with array methods such as map, filter, find and reduce, sort numbers and text in the order readers expect, and copy and combine arrays with spread syntax without changing the originals by accident.

BeginnerLesson 2 of 9 in JavaScript Programming Course

What you will learn

  1. Write for, while and do...while loops that run the right number of times, trace them step by step, and control them with break and continue.
    • Count and repeat with a for loop
      Write a for loop from its three parts, trace its counter from the first to the last iteration, and build a running total.
    • Repeat while a condition holds
      Use while and do...while loops when the number of repetitions is not known in advance, and make sure every loop can end.
    • Stop, skip and nest loops
      Leave a loop early with break, skip an iteration with continue, and place one loop inside another to work through grids and pairs.
  2. Create arrays, read and change their elements by index, add and remove items, and search arrays or convert them to and from text.
    • Create an array and read its elements
      Write array literals, read elements by their zero-based index, and use length and at() to reach the last element.
    • Add, remove and replace elements
      Change arrays in place with index assignment, push, pop, shift, unshift and splice, copy parts with slice, and tell methods that change an array from methods that return a new one.
    • Search an array and convert it to and from text
      Check whether an array contains a value, find a value's position, compare arrays correctly, and turn strings into arrays and back with split and join.
  3. Visit every element of an array with for and for...of loops, and use standard loop patterns to total, count, find and build results.
    • Walk through an array with for and for...of
      Choose between an index-based for loop and for...of, get the index when you need it, and avoid for...in and changing an array's length while looping over it.
    • Total, count, find and build with loop patterns
      Apply the accumulator, counter, maximum, search and build-a-new-array patterns to real lists of data, and trace them step by step.
  4. Pass short arrow functions to array methods, and use forEach, map, filter, find, some, every and reduce to transform, select, search and summarize data.
    • Pass a function to an array method
      Write short arrow functions, know what a callback receives and must return, and use forEach to run code for each element.
    • Transform and select elements with map and filter
      Use map to turn every element into a new value and filter to keep the elements that pass a test, and chain the two.
    • Find elements and test conditions
      Use find, findIndex, findLast, findLastIndex, some and every to locate one element or check a condition across a list.
    • Combine all elements into one value with reduce
      Use reduce with an accumulator and a starting value to compute totals, counts and extremes, and trace each step.
  5. Sort numbers and text in the correct order, including the alphabetical order of the reader's language, and copy and combine arrays with spread syntax without changing the originals by accident.
    • Sort and reverse arrays of numbers and strings
      Use sort with a compare function, know that sort changes the array, and use toSorted and toReversed to get sorted or reversed copies.
    • Sort and present text for readers in any language
      Compare strings with localeCompare and Intl.Collator for natural alphabetical order, keep dates in a sortable form, and turn arrays into readable text with join, Intl.ListFormat and number formatting.
    • Copy and combine arrays with spread syntax
      Understand that array variables refer to a shared array, and use spread syntax to copy, merge and insert arrays and to pass array elements to a function as separate values.

JavaScript Loops and Arrays study guide

5 chapters

1

Repeat code with loops

Repeating code needs a clear starting point, a test and a way to make progress. Counting loops make the number of steps visible; condition-based loops let the data decide when to stop. Trace each changing variable to see what runs before and after a check, then use early exits and nested loops to handle searches, skipped values and pairs. Small changes to an endpoint or an update can change the whole result.

1.1 Control a counting loop

A loop repeats a block of code. Each run of its body is an iteration. You can change how many times the work repeats by changing the loop's counter and condition, without copying the body.

Read the three parts
for (let i = 1; i <= 5; i++) {
  console.log(i);
}

The parentheses contain an initialization, a condition and an update, separated by semicolons. let i = 1 runs once. JavaScript then checks i <= 5. If it is true, the body prints i, the update i++ adds 1, and JavaScript checks the condition again. A false condition ends the loop before another run of the body.

Value before the checkConditionAction
1truePrint 1; update to 2
2, 3, 4true each timePrint each value and update
5truePrint 5; update to 6
6falseStop

There are five iterations but six condition checks. The final failed check does not run the body. A loop whose condition is false at the start has no iterations.

Choose the endpoints and step

for (let i = 0; i < 10; i++) visits 0 through 9. Starting at 1 with i <= 10 visits 1 through 10. Both run ten times. For a step of 1 from a toward b, when b is at least a, < b gives b - a iterations and <= b gives b - a + 1.

The update can take larger steps: for (let i = 0; i <= 20; i += 5) visits 0, 5, 10, 15, 20. Counting backward needs both a decreasing update and a matching condition: for (let i = 3; i >= 1; i--) visits 3, 2, 1. Write down the first and last intended values before choosing < or <=; this catches an off-by-one error.

Keep a running total
let total = 0;
for (let i = 1; i <= 100; i++) {
  total += i;
}
console.log(total); // 5050

total is an accumulator: it carries the result from one iteration into the next. After the first three iterations it holds 1, then 3, then 6. Put its declaration before the loop so it is initialized once. Declaring it inside the body would reset it each time and make it unavailable after the loop.

Diagnose a loop that behaves strangely

The header's counter uses let because i++ reassigns it. A const counter allows the first body run but throws a TypeError at the update. A let i declared in the header belongs to the loop; reading it afterward raises a ReferenceError unless another variable named i exists outside.

A semicolon immediately after the header gives the loop an empty body. In for (let i = 0; i < 3; i++); { console.log("Hello"); }, the block runs once after the loop. Keep the opening brace attached to the header. Finally, check the update's direction: starting at 0 with i < 5 and i-- moves away from the stopping point and never ends.

Key Takeaways

  • Initialization runs once; the condition runs before each iteration; the update follows the body.
  • Check the first and last counter values to catch an off-by-one error.
  • Declare a running total before the loop so earlier work is retained.
  • Use let for a counter that changes, and move it toward the stopping point.

1.2 Repeat until a condition changes

Some tasks end when a result reaches a target, not after a known number of steps. A while loop checks that stopping condition before each repetition. A do...while loop checks it after the body.

Check first with while
let balance = 1000;
let years = 0;
while (balance < 1500) {
  balance = balance * 1.05;
  years++;
}
console.log(years); // 9

The balance grows by 5% per year. Both variables are initialized before the loop. After eight repetitions the balance is about 1477.46, below the target, so another repetition is needed. After nine it is about 1551.33; the next check is false. Keep the full balance during the calculation and round only the displayed result.

If a while condition is false initially, the body runs zero times. For a simple counting loop, put the initialization before while and the update at the end of the body. This preserves a for loop's behavior when there is no continue. With continue, the update needs extra care because it may be skipped.

Run once before checking
let n = 4096;
let digits = 0;
do {
  n = Math.floor(n / 10);
  digits++;
} while (n > 0);
console.log(digits); // 4

Math.floor rounds down. Here each division removes the last digit: 4096 becomes 409, then 40, 4 and 0. Each removal increases digits. Starting with 0 still runs once, correctly counting its one digit. A prechecked while (n > 0) would skip that case and report zero digits. This digit-counting method is for nonnegative whole numbers.

LoopWhen the condition is checkedMinimum body runs
whileBefore the bodyZero
do...whileAfter the bodyOne

With let n = 10, a do...while body that prints n runs once even if its condition is n < 5. The same prechecked condition prints nothing. The semicolon belongs after the final condition in do...while.

Make progress toward an exit

An infinite loop keeps repeating without terminating. Forgetting n++ in let n = 0; while (n < 3) { console.log(n); } leaves the condition true forever. Long-running code can freeze a browser tab. Trace what changes the condition, and stop a stuck script with the browser's controls.

A compound condition such as attempts < 3 && !found continues only while both tests are true. It stops when three attempts have been used or a result is found. For a nonnegative integer decreasing toward zero, while (count > 0) makes a countdown clearer than while (count). Negative numbers are truthy too, so truthiness alone does not mean a count is positive.

Avoid equality as a decimal stopping test. Ten additions of 0.1 give 0.9999999999999999 in JavaScript, so while (x !== 1) can pass the intended endpoint forever. A comparison such as x < 1 permits crossing the boundary; an integer counter is better when exactly ten steps are needed. Compute each decimal value from that counter.

Key Takeaways

  • while can run zero times; do...while always runs at least once.
  • Choose a condition based on what must still happen, then change its inputs in the body.
  • A compound condition can stop work when a limit is reached or a result is found.
  • Floating-point rounding makes exact decimal equality a poor stopping test.
  • Use whole-number counters when the number of repetitions must be exact.

1.3 Stop a search, skip work and visit pairs

A loop can leave before its condition becomes false or skip work for just one item. Nested loops let you repeat one sequence inside another, as when visiting rows and columns.

Break or continue

break leaves its loop immediately. To find the first multiple of 7 above 50:

for (let n = 51; n <= 100; n++) {
  if (n % 7 === 0) {
    console.log(n); // 56
    break;
  }
}

After printing 56, execution continues after the loop. Values 57 through 100 are never checked. while (true) can use the same pattern when the exit is easiest to test inside the body; a reachable break must provide the exit.

continue skips the rest of the current iteration. In a for loop it still runs the header's update before checking the condition again:

for (let i = 1; i <= 9; i++) {
  if (i % 2 === 0) continue;
  console.log(i);
}

The even values skip the print, so the output is 1, 3, 5, 7, 9. Replacing continue with break would end the loop at 2, leaving only 1 printed.

In a while loop, continue jumps directly to the condition. An update placed later in the body is skipped. If i is 2 and the body starts with if (i === 2) continue;, that value can remain stuck forever. Put the needed update before that jump or express counting with for.

Repeat an inner loop for each row
for (let row = 1; row <= 3; row++) {
  let line = "";
  for (let col = 1; col <= 4; col++) {
    line = line + (row * col) + " ";
  }
  console.log(line.trim());
}

For row = 1, the inner loop visits columns 1 through 4 and builds the text "1 2 3 4". It starts over at column 1 for row 2, producing "2 4 6 8". Row 3 produces "3 6 9 12". The inner body runs twelve times: four columns for each of three rows. Declare line inside the outer body so each row starts with an empty string.

Use different names for the counters. An inner let i hides an outer i, making it hard to read both positions.

Visit each distinct pair once

For four people numbered 0 through 3, start the inner counter at i + 1:

for (let i = 0; i < 4; i++) {
  for (let j = i + 1; j < 4; j++) {
    console.log(i, j);
  }
}

The pairs are 0–1, 0–2, 0–3, 1–2, 1–3, 2–3: six visits. Starting j at 0 would make sixteen visits, including self-pairs and reversed duplicates.

An ordinary break leaves only the innermost loop. To end a whole nested search, label the outer loop, for example outer: for (...), then use break outer; at the match. The label names the loop to leave; it does not change the order in which the pairs are tested.

Key Takeaways

  • break ends a loop; continue skips the rest of one iteration.
  • continue runs a for update but can skip an update inside a while body.
  • The inner loop starts again for each outer iteration.
  • Use j = i + 1 to visit each distinct pair once.
  • An ordinary break leaves the innermost loop.
  • A labeled break can leave an outer loop as well.
2

Store and change lists of data in arrays

A list has both values and positions. Arrays keep those values together while giving each one a numbered index. Reading, replacing, inserting and removing elements all depend on those positions, and edits can move later elements to new indexes. Learn what each method returns as well as what it changes, then choose searches and text conversions that produce the form of result the next step needs.

2.1 Read values and positions in an array

An array stores an ordered list under one name. Its values are called elements. An array literal uses square brackets and commas: const temps = [18, 21, 19, 24];. The literal [] creates an empty array.

Count positions from zero
const colors = ["red", "green", "blue"];
console.log(colors[0]); // "red"
console.log(colors[2]); // "blue"
console.log(colors.length); // 3

An element's index is its position starting from zero. The third element has index 2. length counts indexed slots, including any empty slots. For this gap-free array it is also the element count. The last index is colors.length - 1, so colors[colors.length - 1] reads "blue".

Reading colors[colors.length] asks for index 3, one past the end, and gives undefined. A missing index does not throw an error just because it is missing. colors[5] also gives undefined.

Read from the end

colors.at(-1) reads the last element and colors.at(-2) reads the one before it. Nonnegative indexes work as usual: colors.at(0) reads "red". A negative number in square brackets has a different meaning: colors[-1] does not count from the end and gives undefined for this array.

ExpressionResult
colors[1]"green"
colors.at(-1)"blue"
colors[3]undefined
colors[-1]undefined
Read a list inside a list

An element can itself be an array:

const grid = [[1, 2, 3], [4, 5, 6]];
console.log(grid[1]); // [4, 5, 6]
console.log(grid[1][0]); // 4

The first index selects a row. The second selects a value inside that row. grid.length is 2, while grid[0].length is 3. These lengths describe different arrays. Rows in a nested array can have different lengths.

Arrays can mix types, as in [42, "km", true]. A list of one kind of data, such as temperatures, is easier to process because each element can be handled in the same way.

Recognize an array and avoid empty-slot surprises

typeof [1, 2] returns "object", so it is not a specific array test. Use Array.isArray(value): it returns true for [1, 2] and false for "12".

new Array(3) creates three empty slots; it does not store the single number 3. Use [3] for one element or [0, 0, 0] for three explicit zeros. An empty slot reads as undefined, but it is a gap, not an explicitly stored value. Writing array literals makes the intended contents clear.

Read strings without trying to change them in place

Strings also support indexing, length and at(). "hello"[1] is "e" and "hello".at(-1) is "o". Strings are immutable: assigning to a character position does not replace it. In strict mode, including JavaScript modules, that assignment throws a TypeError. Build a new string when text needs to change.

Key Takeaways

  • Indexes start at 0; the last index is length - 1.
  • at(-1) reads the last element; arr[-1] does not.
  • Read nested arrays one index at a time.
  • Use Array.isArray to identify arrays.
  • Array literals distinguish stored values from empty slots.

2.2 Change an array or copy part of it

Changing an existing array is called mutation. Some methods mutate the array; others return a new array. A method's return value may also be a length or a removed element, so check both the array and the result of the call.

Replace elements and change the ends
const scores = [70, 80, 90];
scores[1] = 85;
console.log(scores); // [70, 85, 90]

const keeps scores pointing to the same array. It does not freeze that array's contents. Assigning scores = [] would throw a TypeError, but index assignment is allowed.

MethodChangeReturn value
push(...items)Add at the endNew length
pop()Remove from the endRemoved element
unshift(...items)Add at the startNew length
shift()Remove from the startRemoved element

For const queue = ["Ana", "Ben"];, queue.push("Cleo") returns 3. The array becomes ["Ana", "Ben", "Cleo"]. Then queue.pop() returns "Cleo" and leaves the first two names. Storing a call to push stores its numeric length, not the updated array. pop and shift return undefined on an empty array. Adding or removing at the start also shifts the other indexes, which can involve more work on long arrays.

Insert and remove in the middle

splice(start, deleteCount, ...items) changes the array and returns an array of removed elements:

const days = ["Mon", "Tue", "Thu", "Fri"];
const removed = days.splice(2, 0, "Wed");
// days: ["Mon", "Tue", "Wed", "Thu", "Fri"]
// removed: []
const nextRemoved = days.splice(1, 2);
// days: ["Mon", "Thu", "Fri"]
// nextRemoved: ["Tue", "Wed"]

The first call starts at index 2, deletes zero items and inserts "Wed" there. The second starts at index 1 and removes two items. Its second argument is a count, not an ending index. Elements after an insertion or removal receive new indexes.

Copy a range with slice

slice(start, end) returns a new array and excludes the ending index. For const t = [10, 20, 30, 40, 50];, t.slice(1, 3) gives [20, 30] and leaves t unchanged. t.slice(-2) copies the last two elements, [40, 50]. With no arguments, t.slice() copies the whole array. The extra letter in splice marks a different operation: it edits the original; slice copies a range.

Keep the list free of accidental gaps

Writing beyond the end creates empty slots. After const a = [1, 2]; a[4] = 5;, the length is 5 and indexes 2 and 3 are gaps. delete a[i] also leaves a gap and preserves the length. Use push to append and splice(i, 1) to remove an element and close the gap.

Assigning a smaller length removes elements from the end. a.length = 0 empties the array. The removed elements do not reappear if the length is later increased.

sort and reverse also mutate arrays. Copying methods include slice, concat, map, filter, toSorted, toReversed, toSpliced and with. When a method returns a new array, save or use that result; the original still holds its earlier contents.

Key Takeaways

  • const prevents reassignment of the variable but allows array mutation.
  • push and unshift return lengths; pop and shift return removed elements.
  • splice edits in place and returns the removed elements.
  • slice copies a range whose ending index is excluded.
  • delete leaves a gap; splice(i, 1) closes it.
  • Setting a smaller length removes elements from the end.
  • Keep the result of a copying method when you need the new array.

2.3 Search values and turn lists into text

A search may need a yes/no result or an element's position. Text conversion has another purpose: it changes the form of data so a list can be read, stored or processed.

Ask whether or where

includes(value) returns a boolean. ["tea", "coffee"].includes("tea") is true; changing the search to "Tea" gives false. Text matching is case-sensitive, and types matter: [5].includes("5") is false.

indexOf(value) returns the first matching index, or -1 when no value matches. lastIndexOf searches from the end. With [3, 7, 3, 9], the first 3 is at index 0 and the last is at index 2. Searching for 5 returns -1.

Do not write if (arr.indexOf(x)). Index 0 is falsy, while -1 is truthy: that test rejects a match at the start and accepts a missing value. Use arr.indexOf(x) !== -1, or use includes when the position is unneeded.

For ordinary values, both methods require the same type and value, like strict equality. Their treatment of NaN differs: [1, NaN].includes(NaN) is true, but [1, NaN].indexOf(NaN) is -1. The equality rule used by includes can match NaN to itself.

Compare contents deliberately

Two separately created arrays are different arrays even when their elements match. [1, 2] === [1, 2] is false; == also compares array identity. To check the same ordered contents, compare lengths and then the values at each matching index. A yes/no membership check alone would not establish the same order or the same number of repetitions.

Join elements into a string
const dateParts = ["2026", "03", "15"];
console.log(dateParts.join("-")); // "2026-03-15"
console.log([1, 2, 3].join()); // "1,2,3"
console.log([1, 2, 3].join("")); // "123"

join places its separator between elements, never after the last one. Its default separator is a comma without spaces. null and undefined elements contribute empty text. Choose the separator explicitly for readable output.

Using + with a string also converts an array to text, but uses commas: "List: " + [1, 2] becomes "List: 1,2". Nested structure is lost in that text: String([1, [2, 3]]) gives "1,2,3". Log the array itself to inspect its structure.

Split text into pieces

"red,green,blue".split(",") returns ["red", "green", "blue"]. The separator must match exactly. Splitting "red, green" on just a comma retains the space at the start of " green"; splitting on ", " removes the comma and that space.

"4,8,15".split(",") returns strings, not numbers. Convert each piece before adding numeric values. Otherwise the + operator can join text instead of finding a total.

For simple letter-based text, "stressed".split("").reverse().join("") produces "desserts". The split makes a fresh array, reverse changes that array, and join rebuilds a string. An empty separator splits UTF-16 code units; some symbols use more than one unit, so this is not a general way to reverse all human-readable text.

Key Takeaways

  • Use includes for membership and indexOf or lastIndexOf for positions.
  • Compare a search index with -1; do not use its truthiness.
  • Separate arrays compare by identity, even when their values look identical.
  • join creates text; split creates an array of strings.
  • Spaces belong to the separator only when you include them explicitly.
  • Convert numeric text before arithmetic.
3

Loop through arrays

Working through a list is easier when the loop exposes the right information. Sometimes the body needs only each value; sometimes it needs an index, a previous value or a backward path through the array. Build reusable patterns for totals, counts, searches and new lists, and watch how each result changes after an iteration. These patterns also explain the array methods that follow.

3.1 Visit array values without skipping them

A loop can visit array positions or take the values directly. Choose the form that exposes the information the body needs. Keep the array's changing indexes in mind when inserting or removing elements.

Use indexes for positions and direction
const fruits = ["apple", "pear", "plum"];
for (let i = 0; i < fruits.length; i++) {
  console.log(fruits[i]);
}

The indexes are 0, 1, 2. The test is < fruits.length, because index 3 is past the end. With <=, an extra iteration would read undefined. Index loops can also go backward, starting at fruits.length - 1 and continuing while i >= 0, or visit every second element with i += 2.

Use for...of for values
for (const fruit of fruits) {
  console.log(fruit.toUpperCase());
}

This prints "APPLE", "PEAR" and "PLUM". fruit holds one value per iteration. const works because each iteration creates a new binding; the loop does not reassign one shared counter. for...of works on strings too. A loop over "banana" can count vowels by testing "aeiou".includes(ch) for each ch.

Changing a local number does not write into the array. After for (let n of nums) { n = n * 2; }, the numeric elements of nums are unchanged. To mutate them, assign through nums[i], or build a new array of doubled numbers.

Get values and indexes together

entries() supplies pairs containing an index and a value. Square brackets in the loop header unpack each pair:

for (const [i, fruit] of fruits.entries()) {
  console.log((i + 1) + ". " + fruit);
}

The output is "1. apple", "2. pear", "3. plum". Array indexes still start at zero; i + 1 changes only the displayed numbering.

NeedUseful loop
Each value in orderfor...of
Positions, reverse order or neighborsIndex-based for
Value and index togetherfor...of over entries()

for...in visits property names. For arrays, its indexes are strings, and it can include extra properties. Use the array loop forms above to process elements.

Avoid skipping shifted elements
const nums = [2, 4, 5, 6];
for (let i = 0; i < nums.length; i++) {
  if (nums[i] % 2 === 0) nums.splice(i, 1);
}
// nums is [4, 5]

At index 0, removing 2 shifts 4 into index 0. The update moves i to 1, so 4 is skipped. The loop then sees 5 and removes 6. The result still contains an even number.

When removing by index, loop backward from the end. Removing an element then shifts only positions already visited. Another approach is to build a new array containing the values to keep. Avoid adding elements to the same array while a loop's stopping test depends on its length; the endpoint can keep moving.

Key Takeaways

  • Visit indexes from 0 while i < arr.length.
  • Use for...of when only values are needed.
  • entries() supplies index-value pairs.
  • Reassigning a local numeric loop variable does not replace an array element.
  • Forward removal can skip shifted elements; loop backward or build a new array.

3.2 Build totals, searches and new lists

Many array tasks use the same small loop patterns. Decide what result you need, choose its starting value, and update it once for each relevant element. A trace shows what the result means after each step.

Accumulate a total and count matches
const temps = [18, 21, 19, 24];
let sum = 0;
let warm = 0;
for (const t of temps) {
  sum += t;
  if (t > 20) warm++;
}

sum adds each temperature; warm adds one only for a temperature above 20 °C. They track different quantities. A trace makes that distinction visible:

tsum after addingwarm after checking
18180
21391
19581
24822

The average is sum / temps.length, giving 20.5 °C. Check the length before dividing: an empty array gives 0 / 0, which is NaN, not a meaningful average.

Track a largest or smallest value

For a nonempty array, initialize the maximum from its first element. Then replace it only when a larger value is found:

const values = [-3, -7, -1, -5];
let max = values[0];
for (const n of values) {
  if (n > max) max = n;
}
// max is -1

Starting at zero would incorrectly retain zero for an all-negative list. Starting at -Infinity also works for a maximum, but an empty input then leaves that starting value. For a minimum, reverse the comparison and choose the first element or Infinity as the start.

Find a first match or test a whole list

A search stores a match and exits with break. With let firstWarm;, the loop can assign firstWarm = t at the first t > 20 and break. It finds 21, leaving later elements unchecked. If nothing matches, the variable stays undefined.

For an "all" test, start a flag at true and set it to false at the first failure. For an "any" test, start at false and set it to true at the first success. With passing scores defined as at least 50, [72, 85, 49] fails the all-passed test at 49. An empty list leaves the starting flag unchanged.

Build changed values and compare neighbors
const km = [1.5, 3, 0.25];
const meters = [];
for (const d of km) {
  meters.push(d * 1000);
}
// meters is [1500, 3000, 250]

The new array starts empty and receives one converted distance per iteration. Put a condition before push when only some values belong in the result.

For day-to-day changes, start at index 1, because index 0 has no previous day:

const changes = [];
for (let i = 1; i < temps.length; i++) {
  changes.push(temps[i] - temps[i - 1]);
}
// changes is [3, -2, 5]

There is one fewer difference than readings. Subtracting in the opposite order would reverse every sign. The same result shapes appear in array methods: map builds transformed values, filter keeps matches, find searches, some and every test, and reduce accumulates. A loop remains useful when one pass needs several results, as with sum and warm.

Key Takeaways

  • Start totals and counts at zero, then update each for its own purpose.
  • Initialize an extreme from the data or an appropriate infinity.
  • A first-match search stops with break.
  • All/any flags start with opposite boolean values.
  • Build a new array with push to preserve the original.
  • Start neighbor comparisons at index 1.
  • Trace changing variables to find where a result first goes wrong.
4

Process arrays with callback methods

Array methods let a short function describe what should happen to each value. The method manages the traversal while the callback supplies a transformation, a test or the next running result. Read the returned value carefully: it may be an array, an element, an index, a boolean or a total. The same few callback rules support all of these tasks, including reliable behavior when a list is empty.

4.1 Give an array method a callback

A function takes inputs, runs code and can return a result. A callback is a function handed to another function to call. Array methods use callbacks to describe the work for each element.

Write a short arrow function

n => n * 2 takes a parameter named n and returns its doubled value. The arrow separates the inputs from the body. A single parameter can omit parentheses. Zero or multiple parameters need them: () => 0 and (a, b) => a - b.

const double = n => n * 2;
const doubled = [1, 2, 3].map(double);
// doubled is [2, 4, 6]

double names the function itself. The method calls it with each number. Writing map(double()) would call it immediately and pass the result instead of the function. With a named test such as function isEven(n) { return n % 2 === 0; }, use filter(isEven) to let the method supply each element.

Return from a block body

An expression after the arrow is returned automatically. Curly braces create a block, so a result needs an explicit return:

const double = n => {
  const doubled = n * 2;
  return doubled;
};

Without return, the function returns undefined. [1, 2, 3].map(n => { n * 2; }) therefore produces [undefined, undefined, undefined]. The multiplication runs, but its value never becomes the callback's result.

Read callback arguments by position

Methods such as map, filter and forEach pass the element first, its zero-based index second, and the whole array third. In (name, i) => ..., the names are your choice; their positions determine what they receive. Leave off unused parameters from the end. Other methods have different signatures: reduce also receives an accumulator, and a sorting callback receives two values to compare.

Use forEach for actions
const letters = ["a", "b"];
const result = letters.forEach((letter, i) => {
  console.log(i + ": " + letter);
});
// Prints "0: a" and "1: b".
// result is undefined.

Printing is a side effect: an action performed while the callback runs. forEach discards callback return values and itself returns undefined. Use map when a new array of results is needed. Returning a value from a forEach callback does not change that rule.

A return in this callback ends only the current call; the method continues to the next element. break cannot be used inside a callback to exit forEach. Choose for...of with break, or a search method such as find or some, when later work should stop at a match.

These callback methods do not themselves edit the source array. The callback can still mutate it, for example through index assignment or push. Keeping callbacks focused on their returned value or intended action makes it easier to reason about what the source will contain afterward.

Key Takeaways

  • Pass a callback function itself, without calling it first.
  • An expression body returns its value automatically; a block body needs return.
  • Callback parameter positions determine their meanings.
  • forEach performs actions and returns undefined.

4.2 Transform every value or keep matching values

Choose an array method by the shape of the result. map produces a value for every present element. filter keeps the original elements that pass a test. Both return new arrays.

Transform with map
const km = [1.5, 3, 0.25];
const meters = km.map(d => d * 1000);
// meters is [1500, 3000, 250]; km is unchanged.

The callback's return becomes the element at the matching position. For a gap-free input there is one callback call per element, and the result has the same length. Mapping string elements works too: ["ana", "ben"].map(s => s.toUpperCase()) gives ["ANA", "BEN"].

The second callback parameter gives the index. ["Ana", "Ben"].map((name, i) => (i + 1) + ". " + name) builds ["1. Ana", "2. Ben"]. If the callback has a block body, explicitly return the value to store.

Select with filter
const temps = [18, 21, 19, 24];
const warm = temps.filter(t => t > 20);
// warm is [21, 24]

filter keeps an element when the callback returns a truthy result. It keeps the element itself, not the callback's boolean. The retained values stay in their original order. The result can contain all elements, some, or none; temps.filter(t => t > 30) is [].

Do not return the element itself when zero is valid data. [0, 5, 0, 3].filter(n => n) drops both zeros because they are falsy. A condition such as n !== null removes missing readings represented by null while preserving zero. State the actual rule for keeping an element.

Result neededMethod
One transformed value per elementmap
All original elements passing a testfilter
Some elements, then transformedfilter followed by map

Using map with a conditional that returns undefined for rejected elements does not remove them. Those undefined results still occupy positions in the new array.

Follow a chain left to right

[12, 7, 30, 4].filter(n => n >= 10).map(n => n / 2) first creates [12, 30], then [6, 15]. The second callback receives only the retained elements. Filtering before mapping is appropriate when the test refers to the original values. Changing the order can change what the test sees.

Convert numeric text deliberately
const numbers = "4,8,15".split(",").map(Number);
// numbers is [4, 8, 15]

Number receives each text piece and produces a number. Passing parseInt directly is a trap: its second argument is a number base, while map supplies the index there. ["10", "10", "10"].map(parseInt) gives [10, NaN, 2]. Use map(s => parseInt(s, 10)) to fix the base, or map(Number) for these whole numeric strings.

Neither map nor filter replaces the source. temps.map(t => t + 1); alone throws away its newly calculated array. Save it, return it from a function, or use it in a chain.

Key Takeaways

  • map returns transformed values in a new array of the same length.
  • filter returns matching original elements in their existing order.
  • A filter test must express the intended rule so valid zeros are retained.
  • Chained callbacks operate on the previous method's result.
  • Use Number or a one-argument wrapper instead of map(parseInt).
  • Store or use the new array; the source is unchanged.

4.3 Find one match and ask any or all

Some questions need one value, others a position or a yes/no answer. Search methods can stop once that answer is known. Choosing the right return type makes later conditions easier to write correctly.

Choose a value or an index
const temps = [18, 21, 19, 24];
console.log(temps.find(t => t > 20)); // 21
console.log(temps.findIndex(t => t > 20)); // 1
console.log(temps.findLast(t => t > 20)); // 24
console.log(temps.findLastIndex(t => t > 20)); // 3

find searches from the start and returns the first matching element. findIndex returns its index. Their Last forms search backward. All four stop when they find the requested match.

MethodMatch resultNo-match result
find, findLastElementundefined
findIndex, findLastIndexIndex-1
filterArray of all matches[]

temps.find(t => t > 30) returns undefined; temps.findIndex(t => t > 30) returns -1. Before passing a found index to splice, check i !== -1. Otherwise, splice(-1, 1) removes the last element even though no match was found.

Preserve falsy matches

[3, 0, 5].find(n => n < 1) returns 0, a successful match. if (result) wrongly treats it as failure because zero is falsy. For numeric data, result !== undefined distinguishes zero from no match. If an array can itself contain undefined as a matching value, use findIndex and compare the result with -1; the value alone cannot distinguish those cases.

filter is appropriate when all matches are needed. [5, 12, 8, 130].filter(n => n > 10) gives [12, 130]; find returns just 12. Getting filter(...)[0] computes the entire matching array before reading its first value.

Test any or all
const scores = [72, 85, 49];
const anyFailed = scores.some(s => s < 50); // true
const allPassed = scores.every(s => s >= 50); // false

some stops at the first success. every stops at the first failure. Their answers are booleans, not elements. In these calls the 49 makes some succeed and every fail.

For an empty array, some returns false because nothing passes. every returns true because nothing fails. If a completed set of results must contain at least one score, combine the tests: scores.length > 0 && scores.every(s => s >= 50). The length condition handles emptiness; every checks the elements.

Choose exact membership or a custom test

includes("ana") looks for exactly that value. A case-insensitive search needs a callback: names.some(n => n.toLowerCase() === "ana"). This can accept both "Ana" and "ANA". Use includes for a known value, and a callback search when each element must be tested by a rule.

Key Takeaways

  • Choose value, index, array or boolean according to the result you need.
  • findLast and findLastIndex search from the end.
  • Test an index against -1 before using it to edit an array.
  • A falsy element such as 0 can be a real match.
  • some stops at a success; every stops at a failure.
  • Empty arrays give false for some and true for every.

4.4 Carry one result through reduce

reduce carries an accumulator from one element to the next. Its callback returns the accumulator for the following step. After the last element, the method returns that final value.

Trace a total
const temps = [18, 21, 19, 24];
const total = temps.reduce((sum, t) => sum + t, 0);
// total is 82

The 0 is the initial accumulator. The callback receives sum first and the current temperature t second. Its returned sum becomes the next call's first argument.

Accumulator beforeElementReturned accumulator
01818
182139
391958
582482

This is the same running total as a loop with let sum = 0. A callback also has optional index and array arguments after the accumulator and element. Parameter names are flexible, but their order is fixed.

Supply a useful starting value

With an initial value, reduction starts at the first element. Without one, the first present element becomes the accumulator and callback calls start with the next present element. On an empty array, omitting the initial value throws a TypeError. [].reduce((sum, n) => sum + n, 0) safely returns 0 because no callback call is needed.

The start also establishes the kind of result. Use 0 for totals or counts and "" for text. ["a", "b", "c"].reduce((text, s) => text + s.toUpperCase(), "") builds "ABC". A numeric total that starts with a string can accidentally concatenate text through +.

Count and find an extreme
const scores = [72, 85, 49];
const passed = scores.reduce(
  (count, s) => s >= 50 ? count + 1 : count,
  0
);
// passed is 2

Passing adds one; failing returns the unchanged count. Every branch supplies a next accumulator. For a maximum, return the larger value: [-3, -7, -1, -5].reduce((max, n) => n > max ? n : max, -Infinity) gives -1. Starting at zero would be wrong for this all-negative list. Empty input leaves -Infinity, so handle that outcome when a real maximum is required.

Return on every path

A block callback needs return. (sum, n) => { sum + n; } returns undefined, so the reduction's final result is undefined. A partly missing return is also dangerous. In a count over [72, 49, 85], returning only for a pass gives 1 first, then undefined at 49, then NaN when adding one at 85. Return the unchanged accumulator when an element makes no contribution.

Combine operations without hiding the task

The total of passing scores is scores.filter(s => s >= 50).reduce((sum, s) => sum + s, 0), which gives 157. An average needs a separate count: temps.reduce((sum, t) => sum + t, 0) / temps.length gives 20.5 °C. Check the length first, because empty input gives NaN after division. If a callback starts doing several unrelated jobs, a for...of loop can show the changing results more clearly.

Key Takeaways

  • reduce passes the accumulator first and the element second.
  • The callback must return the next accumulator on every path.
  • An explicit initial value makes empty-input behavior predictable.
  • Choose the starting value for the result: total, count, text or extreme.
  • An average needs both a total and a nonzero count.
5

Sort, copy and combine arrays

Ordering a list and copying it are separate choices. A numeric sort needs different comparison rules from a list of names, and language affects the order readers expect. Decide whether the original sequence must be preserved before choosing an editing or copying method. References and shallow copies explain which later changes stay local and which remain visible through another array name.

5.1 Sort numbers and preserve the original

Sorting chooses an order by comparing elements. Reversing simply flips the existing order. Both operations have methods that edit an array and methods that create a copy.

Understand the default order

[10, 9, 1, 100].sort() gives [1, 10, 100, 9]. Without a compare function, sort compares elements as strings, character by character using UTF-16 code units. "100" starts with "1", which comes before "9". The stored elements remain numbers; only the comparison uses their text form.

For strings, this default can also surprise readers. ["banana", "Cherry", "apple"].sort() gives ["Cherry", "apple", "banana"], because capital ASCII letters come before lowercase ones. Accented letters can be separated from the letters readers group them with. Use language-aware comparison for human alphabetical order.

Return the right sign

A compare function receives two elements, a and b. A negative return places a before b; a positive return places it after b; zero treats them as equal for sorting.

const nums = [10, 9, 1, 100];
nums.sort((a, b) => a - b);
// nums is [1, 9, 10, 100]

Comparing 10 with 9 produces positive 1, so 9 goes before 10. For descending numeric order, use (a, b) => b - a. Return a number with a meaningful sign. (a, b) => a > b returns only true or false, which become 1 or 0; it never reports that a belongs before b. Such a comparator gives unreliable ordering.

Sorting is stable: elements comparing as equal keep their original relative order. ["kiwi", "fig", "pear", "plum"].sort((a, b) => a.length - b.length) gives ["fig", "kiwi", "pear", "plum"]. The three four-letter words retain their order.

Choose mutation or a copy
MethodEffect on sourceReturned array
sort(compare)Sorts source in placeSame array
toSorted(compare)Leaves source unchangedNew sorted array
reverse()Reverses source in placeSame array
toReversed()Leaves source unchangedNew reversed array

const sorted = scores.sort((a, b) => a - b); gives a second name for the same now-sorted array. It does not preserve the earlier order. For a new sorted array, use scores.toSorted((a, b) => a - b), or make a spread copy before sort.

[3, 1, 2].toReversed() gives [2, 1, 3]. That is a reversed sequence, not descending numeric order. To put largest values first, use a descending comparator or sort ascending before reversing.

Check types before sorting numeric text

Values from split are strings. ["10", "9", "100"].sort() gives ["10", "100", "9"]. Subtraction in a comparator converts numeric strings during comparison but leaves the elements as strings. Convert first with map(Number) when the values are numeric data, then use a numeric comparator. This also prepares the data for later addition without accidental text concatenation.

Key Takeaways

  • Default sorting compares text, even for numeric elements.
  • Use a - b for ascending numbers and b - a for descending numbers.
  • A comparator returns a negative number, zero or a positive number.
  • Equal comparisons preserve relative order.
  • sort and reverse mutate; toSorted and toReversed copy.
  • Reversing the current order does not necessarily sort it.

5.2 Order and format data for the reader

People expect text order and number formatting to follow a language's conventions. Keep values in forms that are easy to process, choose an explicit locale for text comparison, and format the final output for the reader.

Compare text with locale rules

a.localeCompare(b, locale) returns a negative number when a comes before b, a positive number when it comes after, and zero when they compare as equal. Only the sign is guaranteed, not an exact -1 or 1.

const names = ["Zoe", "Émile", "adam"];
const sorted = names.toSorted((a, b) => a.localeCompare(b, "en"));
// sorted is ["adam", "Émile", "Zoe"]

A locale is a language tag such as "en", "de" or "sv". German places "ä" before "z", while Swedish places it after "z". Pass the page's intended language to make that choice explicit. Without a locale, the runtime's default settings decide the order.

Plain < comparisons still compare character codes. Subtracting words produces NaN, which acts like an equal comparison in sorting; it does not create alphabetical order.

Set useful comparison options

With { numeric: true }, runs of digits compare numerically. Sorting ["file10", "file2", "file1"] with (a, b) => a.localeCompare(b, "en", { numeric: true }) gives ["file1", "file2", "file10"]. A plain text sort puts "file10" before "file2".

In English, { sensitivity: "base" } treats case and accent variants such as "a", "A" and "á" as equal. These rules depend on the language: Swedish treats "a" and "ä" as different base letters. Use the intended locale when matching as well as when sorting.

For many comparisons, reuse a collator:

const collator = new Intl.Collator("en", { numeric: true });
const sorted = files.toSorted(collator.compare);

collator.compare is already a comparison function. Creating it once avoids repeatedly setting up the same locale options during a large sort.

Sort dates before formatting them

Fixed-width YYYY-MM-DD strings put the year before the month and day. Text sorting then follows date order: ["2026-03-15", "2025-11-02", "2026-01-20"].sort() gives ["2025-11-02", "2026-01-20", "2026-03-15"].

Day-first text such as "15/03/2026" and "20/01/2025" compares the day first, so it can put the later year first. Store and sort these dates in ISO form, then produce display text at the end.

Build readable lists and numbers

join(", ") uses the same separator everywhere. Intl.ListFormat adds the language's final connector:

const list = new Intl.ListFormat("en-US", {
  style: "long", type: "conjunction"
});
list.format(["Ana", "Ben", "Cleo"]);
// "Ana, Ben, and Cleo"

"en-GB" produces "Ana, Ben and Cleo"; "nl" produces "Ana, Ben en Cleo". A disjunction uses "or" in English. Two names give "Ana and Ben" without a comma.

(1234.5).toLocaleString("en-US") gives "1,234.5", while "de-DE" gives "1.234,5". These results are strings. Sort numeric data before applying toLocaleString with map; formatting first replaces numeric values with text whose punctuation affects text sorting.

Key Takeaways

  • Use localeCompare or a reusable Intl.Collator for language-aware order.
  • Use the sign of the comparison result, not an exact -1 or 1.
  • numeric: true orders digit sequences naturally inside names.
  • Fixed-width ISO date strings sort chronologically as text.
  • Intl.ListFormat adds a language-appropriate connector.
  • Sort numbers first and format them last.

5.3 Copy arrays without sharing accidental changes

An array variable holds a reference to an array. Assigning that variable to another name shares the array. Spread syntax can create a new outer array, combine lists or pass elements as separate function arguments.

Separate assignment from copying
const a = [1, 2, 3];
const b = a;
b.push(4);
// a and b both refer to [1, 2, 3, 4].
console.log(a === b); // true

There is one array with two names. const does not prevent either name from being used to mutate it. A new outer array needs an actual copying operation:

const c = [...a];
c.push(5);
// c is [1, 2, 3, 4, 5]; a stays [1, 2, 3, 4].
console.log(c === a); // false

The three dots lay out a's elements inside a new array literal. Leaving them out has a different effect: [a] creates a one-element array whose element is the entire array a. [...a] contains a's elements individually.

Combine and insert

[...[1, 2], ...[3, 4]] gives [1, 2, 3, 4], as does [1, 2].concat([3, 4]). [...first, 99, ...second] places one extra element between two lists. [...list, "new"] creates an extended array while list.push("new") edits the existing one. Spread preserves the element order of each input.

Recognize a shallow copy
const grid = [[1, 2], [3, 4]];
const copy = [...grid];
copy[0].push(9);
// grid[0] and copy[0] are both [1, 2, 9].

The outer arrays differ, but their row elements still point to the same inner arrays. This is a shallow copy. Replacing copy[0] with a new row would change only the copied outer array; mutating the existing row changes the shared row. structuredClone(grid) makes an independent deep copy of these nested arrays.

Spread values into a call

Math.max(...[3, 9, 4]) supplies three separate arguments and returns 9. Passing the array directly, Math.max([3, 9, 4]), supplies one array and gives NaN. Empty spread gives Math.max(...[]) === -Infinity and Math.min(...[]) === Infinity.

Very large arrays can exceed an engine's argument limit when spread into a call. There is no universal safe element count. Use a loop or reduce to find an extreme for a large input. Spread in an array literal does not create a function-argument list.

Spread strings and update copies

[..."hello"] produces five letter strings. String spread visits Unicode code points: [..."a😀"] has two elements, while "a😀".split("") has three UTF-16 code units. Some visible symbols combine several code points, so spreading is not a general count of visible characters. A number is not iterable; [...5] throws a TypeError.

In a parameter list, function total(...nums) uses rest to gather arguments into an array. Spread in a call does the opposite: it supplies separate arguments.

For copy-based updates, [10, 20, 30].with(1, 25) gives [10, 25, 30] and .toSpliced(1, 1) gives [10, 30]. toSorted and toReversed also preserve the source. These are shallow copies, so the same inner-array sharing rule applies.

Key Takeaways

  • Assignment shares an array; spread in an array literal creates a new outer array.
  • Leaving out spread nests an array as one element.
  • Spread can combine arrays and insert extra elements without mutation.
  • A shallow copy still shares inner arrays; structuredClone copies these nested arrays deeply.
  • Call spread supplies separate arguments and is unsuitable for unbounded input sizes.
  • String spread visits code points; rest parameters gather arguments.
  • with and toSpliced make changed copies.

JavaScript Loops and Arrays examples

5 Walkthroughs

1

Trace a loop from its first check to its exit

12 steps
Follow a counter and a running total, compare prechecked and postchecked loops, then control a nested search.
  1. 1
    IntroductionFollow what changes

    A loop repeats a body, but its result depends on the order of checks and changes. We will follow a small total one iteration at a time, then choose a condition-based loop (while checks first, do...while after one run) and control a nested search with break and continue to leave or skip.

    Keep two questions separate: what value reaches the body, and what value makes the next check fail? The final failed check is part of the control flow even though it performs no body work.

  2. 2
    ExampleSet up a running total

    We want the total of 2, 4 and 6. The counter chooses each number, while a separate accumulator retains their sum.

    let total = 0;
    for (let n = 2; n <= 6; n += 2) {
      total += n;
    }
    

    Initialization sets n to 2 once. The first check, 2 <= 6, succeeds. The first body run adds two to zero, leaving total at 2. The update then changes n to 4.

  3. 3
    ExampleTrace the remaining checks

    The next check accepts 4, so the total becomes 2 + 4, or 6. The update takes the counter to 6, which still passes n <= 6. Adding that final value makes the total 12.

    Afterward, the update changes n to 8. Now 8 <= 6 is false, and the loop stops. The body ran three times, and the condition was checked four times. No eight was added to the total.

  4. 4
    ChallengeChange one endpoint

    If the loop above used n < 6 instead of n <= 6, what would its final total be, and why?

    ---reveal---

    The total would be 6: only 2 and 4 reach the body. At n = 6, the condition is already false, so six is never added. The update still reaches six, but reaching a value in the header does not guarantee an iteration using it.

  5. 5
    ExplanationLet a result decide when to stop

    Suppose a batch size starts at 5 and doubles until it reaches at least 30. A while loop can express the unfinished work directly.

    let size = 5;
    let rounds = 0;
    while (size < 30) {
      size *= 2;
      rounds++;
    }
    

    The sizes become 10, 20 and 40. The loop ends with three rounds, because forty is the first reached size for which another doubling is unnecessary.

  6. 6
    Key InsightDecide whether a first run is required

    A while loop checks before doing anything. If the starting size is already 40, the previous loop runs zero times. A do...while loop would double it once before discovering that another run is unnecessary.

    Use that postcheck when one run is part of the task. Counting digits by removing one digit at a time needs to count zero as a one-digit number, which makes a first body run useful.

  7. 7
    ChallengeRead a postchecked loop

    What are n and runs after this code?

    let n = 1;
    let runs = 0;
    do {
      n *= 3;
      runs++;
    } while (n < 8);
    

    ---reveal---

    n is 9 and runs is 2. The first body produces three and the check passes. The second produces nine and its check fails. The test happens after each multiplication, so the final value may cross the boundary.

  8. 8
    ExampleSkip a value without ending the loop

    This loop prints only the allowed counters.

    for (let n = 1; n <= 5; n++) {
      if (n === 3) continue;
      console.log(n);
    }
    

    It prints 1, 2, 4, 5. At three, continue skips the print, but the header update still moves to four. With break instead, the whole loop would stop at three and no later value would print.

  9. 9
    ChallengeFind an update that gets skipped

    Why does this code stop making progress at n = 2?

    let n = 0;
    while (n < 4) {
      if (n === 2) continue;
      n++;
    }
    

    ---reveal---

    Continue jumps directly to the while condition and skips n++. At two, every later check is true and every body run skips the update again. Increment in that branch before continuing, or use a for loop whose header performs the update.

  10. 10
    ExampleFollow an inner search

    For each outer value, an inner loop starts over.

    for (let a = 1; a <= 3; a++) {
      for (let b = 1; b <= 4; b++) {
        if (a * b === 6) break;
        console.log(a, b);
      }
    }
    

    At a = 2, reaching b = 3 ends that inner loop before printing the pair. The outer loop still advances to three. An ordinary break controls the innermost loop only.

  11. 11
    ChallengeEnd the whole nested search

    The nested search should stop completely at its first product of six. What change achieves this, and which pair triggers it?

    ---reveal---

    Label the outer loop outer: and replace the break with break outer;. The first matching pair is a = 2, b = 3: row one has no product of six, then row two reaches it at its third column. Both loops end at that point, so row three never runs.

  12. 12
    RecapRead the control path

    Trace initialization once, then follow each condition, body and update in order. Count only successful entries into the body as iterations.

    A while loop may skip the body entirely; a do...while loop cannot. Continue keeps the next iteration possible but can bypass a while-loop update. Break ends its loop, and a label can extend that exit to an outer search. In every case, identify the next statement execution reaches.

2

Track an array and each method result

11 steps
Read indexed data, follow an insertion and removal, then turn a searched list into display text.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionTrack two results of an edit
  2. 2
    ExampleMatch values to indexes
  3. 3
    ChallengeRead a nested schedule
  4. 4
    ExampleAdd a task and keep its return
  5. 5
    ExampleReplace a task with splice
  6. 6
    ChallengeCopy a window
  7. 7
    ExplanationSearch a position explicitly
  8. 8
    ChallengeCut and join text
  9. 9
    Key InsightKeep numeric text separate from numbers
  10. 10
    ChallengeSearch before removing
  11. 11
    RecapSeparate positions, edits and text
3

Turn a loop into a useful result

10 steps
Choose a traversal, calculate a total and count, then build changes between neighboring readings.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionChoose what the body needs
  2. 2
    ExplanationRead values directly
  3. 3
    ChallengeVisit every second position
  4. 4
    ExampleAdd a total and count long trips
  5. 5
    ExampleUse the completed total
  6. 6
    ChallengeFind an extreme without inventing zero
  7. 7
    ExampleBuild neighbor differences
  8. 8
    ChallengeKeep only increases
  9. 9
    TipRemove from the end when indexes shift
  10. 10
    RecapChoose a start for each result
4

Follow a callback pipeline

15 steps
Return values from callbacks, select and transform readings, search them and trace a reduction.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionLet the method manage the visits
  2. 2
    ExplanationReturn an expression or a block result
  3. 3
    ChallengeChoose a method for printed output
  4. 4
    ExampleKeep selected readings
  5. 5
    ExampleTransform the selected values
  6. 6
    ChallengeKeep valid zeros
  7. 7
    ExplanationSearch for one value or its position
  8. 8
    ChallengeRecognize a zero match
  9. 9
    Key InsightAny and all settle at different moments
  10. 10
    ExampleStart a reduction explicitly
  11. 11
    TipKeep a next accumulator on every path
  12. 12
    ChallengeTrace a filtered total
  13. 13
    ChallengeDiagnose a conversion callback
  14. 14
    ChallengeChoose all matches or one match
  15. 15
    RecapRead each returned shape
5

Preserve data while ordering and formatting it

13 steps
Choose comparison rules, sort numeric data before formatting and follow shallow-copy behavior.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionMake order and identity separate choices
  2. 2
    ExampleCheck the default order
  3. 3
    ExplanationUse the comparator sign
  4. 4
    ChallengeProtect the source order
  5. 5
    ExampleLet language decide text order
  6. 6
    ChallengeOrder numbered labels
  7. 7
    ConnectionFinish calculations before display
  8. 8
    ExampleGive the same array a second name
  9. 9
    ExampleCopy the outer list
  10. 10
    ChallengeFind a shared inner row
  11. 11
    TipPass arguments without building a huge call
  12. 12
    ChallengeCombine order, copy and formatting
  13. 13
    RecapTrace what is shared and what is returned

JavaScript Loops and Arrays practice questions

40 Practice Questions in 4 sets

Set 1: Trace loops and read array positions10 Practice Questions

Question 1 of 10

How many times does this loop body run?

for (let i = 2; i < 7; i++) {
  console.log(i);
}
  1. 4 times
  2. 6 times
  3. 5 times
  4. 7 times
Show answerHide answer
Answer: C
The body runs at counter values 2, 3, 4, 5 and 6, giving five iterations. At 7, the condition is false before the body can run. Counting six iterations would include that failed check as though it were another body run.

Question 2 of 10

What does ["oak", "pine", "elm", "fir"].at(-2) return?
  1. "elm"
  2. "pine"
  3. "fir"
  4. undefined
Show answerHide answer
Answer: A
A negative index in at counts backward: -1 is the last element, "fir", and -2 is "elm". "pine" is at the positive index 1; treating the negative index as an ordinary positive position selects the wrong end of the list.

Question 3 of 10

What value is printed?

let n = 8;
do {
  n -= 3;
} while (n > 6);
console.log(n);
  1. 8
  2. 2
  3. 6
  4. 5
Show answerHide answer
Answer: D
The body runs before the first check and subtracts three from eight, leaving five. The condition 5 > 6 is then false, so execution stops. Eight would be the result of incorrectly treating the loop as a prechecked while that never enters.

Question 4 of 10

What value does total hold afterward?

let total = 0;
for (let n = 3; n <= 9; n += 3) {
  total += n;
}
  1. 9
  2. 18
  3. 12
  4. 15
Show answerHide answer
Answer: B
The counter visits 3, 6 and 9; the total becomes 3, then 9, then 18. The <= condition includes the final nine. A total of nine adds only the first two visited values and misses the endpoint rather than retaining all three contributions.

Question 5 of 10

What numbers are printed, in order?

for (let n = 2; n <= 7; n++) {
  if (n === 4) continue;
  if (n === 6) break;
  console.log(n);
}
  1. 2, 3
  2. 2, 3, 5, 6
  3. 2, 3, 5, 7
  4. 2, 3, 5
Show answerHide answer
Answer: D
At four, continue skips the print but still allows the counter update. Five is printed next; at six, break ends the loop before printing. The sequence ending at three confuses continue with an early exit, while a later seven would require the loop to survive the break.

Question 6 of 10

What pair of values results from grid.length and grid[1][2]?

const grid = [[6, 2, 8], [9, 5, 1]];
  1. 3 and 1
  2. 2 and 1
  3. 2 and 5
  4. 6 and 8
Show answerHide answer
Answer: B
The outer array contains two row arrays, so its length is two. Index 1 selects [9, 5, 1], and index 2 inside that row selects one. Reporting a length of three uses a row length for the outer array, mixing the two levels.

Question 7 of 10

How many iterations run before this loop ends?

let size = 3;
let rounds = 0;
while (size < 20) {
  size *= 2;
  rounds++;
}
  1. 3 iterations
  2. 2 iterations
  3. 4 iterations
  4. 6 iterations
Show answerHide answer
Answer: A
The successive sizes after each iteration are 6, 12 and 24. The first two still permit another iteration, but 24 < 20 is false, so the final count is three. Two iterations would stop at twelve even though the loop condition still requires more work.

Question 8 of 10

How many times does count++ run?

let count = 0;
for (let a = 0; a < 4; a++) {
  for (let b = a + 1; b < 4; b++) {
    if (b === 3) break;
    count++;
  }
}
  1. 2 times
  2. 4 times
  3. 3 times
  4. 6 times
Show answerHide answer
Answer: C
For a = 0, the increment runs at b = 1 and 2; for a = 1, it runs at b = 2. At b = 3, each inner loop breaks before incrementing, and a = 3 has no inner iterations. Six counts all distinct pairs but overlooks the early exits.

Question 9 of 10

This conversion should print the same values as a counting loop that skips 2. How can it be repaired while keeping the while form?

let i = 0;
while (i < 4) {
  if (i === 2) continue;
  console.log(i);
  i++;
}
  1. Use if (i === 2) { break; }.
  2. Use if (i === 2) { i++; continue; }.
  3. Move i++ immediately before console.log(i).
  4. Change the condition to i <= 4.
Show answerHide answer
Answer: B
At two, the current code jumps to the condition without updating and gets stuck. Incrementing inside that branch before continuing skips two and lets three print, matching 0, 1, 3. Replacing continue with break ends at two and loses the required later value.

Question 10 of 10

What does [9, 2, 9].lastIndexOf(9) return?
  1. 0
  2. 3
  3. 2
  4. 9
Show answerHide answer
Answer: C
The last nine occupies zero-based index two, so lastIndexOf returns two. Zero is the position of the first nine and would be returned by indexOf. The method reports a position, not the matching value or the array length.
Set 2: Edit arrays and build results with loops10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

What does size hold after these statements?

const tags = ["new", "open"];
const size = tags.push("done");
  1. ["new", "open", "done"]
  2. 3
  3. "done"
  4. 2
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

What are cut and data afterward?

const data = [4, 8, 12, 16];
const cut = data.splice(1, 2, 7);
  1. cut = [8]; data = [4, 7, 12, 16]
  2. cut = [4, 7, 16]; data = [8, 12]
  3. cut = [8, 12]; data = [4, 8, 12, 16]
  4. cut = [8, 12]; data = [4, 7, 16]
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

A search must recognize a value at index zero and reject a missing value. What condition should replace if (items.indexOf(target))?
  1. if (items.indexOf(target) !== -1)
  2. if (items.indexOf(target) > 0)
  3. if (items.indexOf(target) !== 0)
  4. if (items.indexOf(target) === 1)
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

What loop header supplies each string value from labels in order?
  1. for (const label in labels)
  2. for (const label of labels.length)
  3. for (const label of labels)
  4. for (const label in labels.length)
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

What is the final value of count?

let count = 0;
for (const n of [11, 6, 14, 9]) {
  if (n >= 10) count++;
}
  1. 2
  2. 4
  3. 25
  4. 3
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

What remains in values after this code?

const values = [3, 6, 8, 9];
for (let i = 0; i < values.length; i++) {
  if (values[i] % 3 === 0) values.splice(i, 1);
}
  1. [8]
  2. [6, 8, 9]
  3. [3, 8]
  4. [6, 8]
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

What value results from "7;12;5".split(";").join(" / ")?
  1. [7, 12, 5]
  2. "7 / 12 / 5"
  3. "7;12;5"
  4. "7 / 12 / 5 / "
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

What array is built?

const readings = [9, 4, 8, 3];
const rises = [];
for (let i = 1; i < readings.length; i++) {
  const change = readings[i] - readings[i - 1];
  if (change > 0) rises.push(change);
}
  1. [-5, 4, -5]
  2. [8]
  3. [4]
  4. [5, 5]
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

What are the length and final element of a afterward?

const a = [2, 4];
a[5] = 12;
  1. Length 3; final element 12.
  2. Length 5; final element 12.
  3. Length 6; final element undefined.
  4. Length 6; final element 12.
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

A maximum must be an element of a nonempty numeric array, including when every value is negative. Why can starting at 0 produce the wrong result?
  1. Zero forces every comparison to return false for positive data.
  2. Zero may exceed every element and never be replaced.
  3. Zero makes the loop stop after its first negative element.
  4. Zero is added to every element before the comparison runs.
Show answerHide answer

Save this lesson to see this answer.

Set 3: Transform, search and reduce arrays10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

What value does this reduction return?

[6, 3, 5].reduce((total, n) => total + n, 4)
  1. 18
  2. 14
  3. 10
  4. 24
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

What does [8, 0, 6].find(n => n < 2) return, and how should success be tested for this numeric array?
  1. undefined; test result === undefined.
  2. 0; test Boolean(result).
  3. 0; test result !== undefined.
  4. 1; test result !== -1.
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

What does [4, 7].map(n => { n + 3; }) return?
  1. [7, 10]
  2. undefined
  3. [4, 7]
  4. [undefined, undefined]
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

What array results from this expression?

[5, 16, 9, 22].filter(n => n > 10).map(n => n - 2)
  1. [3, 14, 7, 20]
  2. [14, 20]
  3. [16, 22]
  4. [14]
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

What values are printed, and what is assigned to result?

const result = [2, 5, 8].forEach(n => {
  if (n === 5) return;
  console.log(n);
});
  1. Prints 2; result is undefined.
  2. Prints 2, 8; result is [2, 8].
  3. Prints 2, 8; result is undefined.
  4. Prints 2, 5, 8; result is undefined.
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

Valid readings include zero; only null means missing. What expression converts all valid readings to meters?

const km = [0, null, 1.2, 0.4];
  1. km.filter(n => n).map(n => n * 1000)
  2. km.map(n => n * 1000).filter(n => n !== null)
  3. km.filter(n => n !== null).map(n => n * 100)
  4. km.filter(n => n !== null).map(n => n * 1000)
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

What does the code return?

[64, 40, 91].reduce((count, score) => {
  if (score >= 60) return count + 1;
}, 0)
  1. NaN
  2. 2
  3. 1
  4. undefined
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

A report should be true only when at least one score exists and every score is at least 70. What expression handles all input sizes?
  1. scores.every(s => s >= 70)
  2. scores.length > 0 && scores.every(s => s >= 70)
  3. scores.length > 0 && scores.some(s => s >= 70)
  4. scores.length > 0 || scores.every(s => s >= 70)
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

What does this expression produce?

["6", "15", "4"].map(Number)
  .filter(n => n % 2 === 0)
  .map((n, i) => n + i)
  1. [6, 5]
  2. [6, 6]
  3. [6, 4]
  4. ["60", "42"]
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

A nonempty numeric list needs its largest value even when all values are negative. What reduction satisfies that requirement?
  1. nums.reduce((best, n) => n > best ? n : best, 0)
  2. nums.reduce((best, n) => n < best ? n : best, Infinity)
  3. nums.reduce((best, n) => n > best ? n : best, -Infinity)
  4. nums.reduce((best, n) => n > best, -Infinity)
Show answerHide answer

Save this lesson to see this answer.

Set 4: Sort, copy and combine results safely10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

What does [8, 30, 4].toSorted() return?
  1. [4, 8, 30]
  2. [30, 4, 8]
  3. [8, 4, 30]
  4. [8, 30, 4]
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

What arrays do a and c contain afterward?

const a = [6, 2];
const b = a;
const c = [...a];
b.push(9);
c[0] = 1;
  1. a = [1, 2, 9]; c = [1, 2, 9]
  2. a = [6, 2]; c = [1, 2]
  3. a = [6, 2, 9]; c = [1, 2, 9]
  4. a = [6, 2, 9]; c = [1, 2]
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

How can readings be ordered from largest to smallest while preserving its original sequence?
  1. readings.toSorted((a, b) => b - a)
  2. readings.sort((a, b) => b - a)
  3. readings.toReversed()
  4. readings.toSorted((a, b) => a - b)
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

What expression puts "part12", "part3" and "part1" in natural numeric name order without changing parts?
  1. parts.toSorted((a, b) => a.localeCompare(b, "en"))
  2. parts.toSorted((a, b) => a - b)
  3. parts.toSorted((a, b) => a.localeCompare(b, "en", { numeric: true }))
  4. parts.toSorted((a, b) => b.localeCompare(a, "en", { numeric: true }))
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

What are rows[0] and copy[1] afterward?

const rows = [[5], [8]];
const copy = [...rows];
copy[0].push(6);
copy[1] = [2];
  1. rows[0] = [5]; copy[1] = [2]
  2. rows[0] = [5, 6]; copy[1] = [8, 2]
  3. rows[0] = [5, 6]; copy[1] = [2]
  4. rows[0] = [5]; copy[1] = [8, 2]
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

A program formats [1200, 25, 4] with numbers.map(n => n.toLocaleString("de-DE")).toSorted(). How should it order and format the values to preserve numbers and display numeric ascending order?
  1. Numeric toSorted, then format: ["4", "25", "1.200"].
  2. Format, then default toSorted: ["1.200", "25", "4"].
  3. Default toSorted, then format: ["1.200", "25", "4"].
  4. Numeric sort, then format: ["4", "25", "1.200"].
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

What array is returned?

["lion", "ox", "bear", "ant"]
  .toSorted((a, b) => a.length - b.length)
  .toReversed()
  1. ["lion", "bear", "ant", "ox"]
  2. ["bear", "lion", "ox", "ant"]
  3. ["ox", "ant", "lion", "bear"]
  4. ["bear", "lion", "ant", "ox"]
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

What does view contain afterward?

const values = [7, 2, 5];
const i = values.findIndex(n => n < 0);
values.splice(i, 1);
const view = values.toReversed();
  1. [5, 2, 7]
  2. [2, 7]
  3. [7, 2]
  4. [5, 2]
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

What is the length of joined?

const left = [4, 6];
const right = [8, 10, 12];
const joined = [...left, right];
  1. 5
  2. 2
  3. 4
  4. 3
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

These date strings sort incorrectly by time: ["08/02/2027", "19/01/2026", "03/12/2026"] in day/month/year form. What stored strings give chronological text order for the same dates?
  1. ["2026-01-19", "2026-12-03", "2027-02-08"]
  2. ["2026-03-12", "2026-19-01", "2027-08-02"]
  3. ["03/12/2026", "08/02/2027", "19/01/2026"]
  4. ["2027-02-08", "2026-12-03", "2026-01-19"]
Show answerHide answer

Save this lesson to see this answer.

Stuck on your own question? Homework Help

Key Terms

71 Key Terms, each with its definition

A

Accumulator
An accumulator is a variable or callback value that carries a growing result from one processed element to the next.
A temperature total retains the previous sum before adding the current reading at each step.
Array
An array is an ordered collection of values with indexed positions, stored and accessed through a single reference.
The array [18, 21, 19, 24] holds four daily temperature readings under one variable name.
Array identity
Array identity distinguishes one array from another, even when both arrays currently contain the same ordered values.
[1, 2] === [1, 2] is false because the literals create two separate arrays.
Array length
An array length is the number of indexed slots up to the array's endpoint, including gaps between assigned elements.
Assigning index 4 in a shorter array makes its length at least five, even if earlier slots are empty.
Arrow function
An arrow function uses the arrow syntax to define a function, often compactly as parameters followed by one returned expression.
The callback n => n * 2 takes one number and returns a value twice as large.
Ascending order
Ascending order places values from smaller to larger under the chosen comparison, such as a numeric subtraction comparator.
Sorting [10, 9, 1] numerically in ascending order gives [1, 9, 10].

B

Break statement
A break statement immediately exits its enclosing loop, or a specified labeled loop, and resumes execution afterward.
A first-match search uses break so later values are not checked after a match is stored.

C

Callback
A callback is a function passed to another function that invokes it as part of its work, often with each array element.
Map calls its callback with an element and uses the returned value in the new array.
Collator
A collator packages locale comparison rules in a reusable Intl.Collator instance with a ready-made compare function.
A collator with numeric: true sorts names containing digits in natural numeric sequence.
Compare function
A compare function returns a negative, zero or positive number to determine the relative order of two values during sorting.
The comparator (a, b) => a - b puts smaller numeric values before larger ones.
Continue statement
A continue statement skips the remaining body code for the current iteration and proceeds along the loop's next-step path.
An even-number check can use continue to skip printing while a for-loop counter still updates.
Counter
A counter records how many events or matches have occurred, usually starting at zero and increasing by one per match.
A warm-day counter increases only when the current temperature passes the chosen test.

D

Deep copy
A deep copy duplicates nested data as well as its outer container so edits to copied rows do not affect the original rows.
For a grid of number arrays, structuredClone creates independent copies of the inner rows.
Do...while loop
A do...while loop runs its body before testing the condition, so its first iteration happens even if the test then fails.
A digit-counting do...while loop processes zero once, counting it as a one-digit number.

E

Early stopping
Early stopping ends a traversal once its result is settled, avoiding later checks that cannot change the answer.
A find search stops at its first match, while every stops at its first failing test.
Element
An element is a value stored at an array position; it may be a number, string or another array, among other value types.
In ["red", "green", "blue"], the string "green" is the element stored at index 1.
Empty slot
An empty slot is an indexed gap with no stored element; it contributes to array length and reads as undefined.
new Array(3) creates three empty slots, whereas [3] creates one explicitly stored element.
Entries
Entries is an array method that supplies index-value pairs for traversal, allowing both pieces of information to be read together.
for (const [i, name] of names.entries()) can print numbered labels using i + 1.
Every
Every is an array method that returns true when no tested element fails; it stops at a failure and is true for an empty array.
Combine a positive length test with every when an all-passed result must include at least one score.

F

Filter
Filter is an array method that returns original elements whose callback test is truthy, retaining their original order.
A test t => t > 20 selects warm readings without replacing them with boolean values.
Find
Find is an array method that returns the first element passing a callback test, or undefined when no match is found.
Finding a number below one in [3, 0, 5] returns zero, which is a successful but falsy match.
FindIndex
FindIndex is an array method that returns the first position passing a callback test, or negative one when none passes.
A found position can be used for removal after checking that it is not the no-match value -1.
Flag
A flag is a boolean value that records whether a condition has been met, such as finding a match or encountering a failure.
An all-passed flag starts true and changes to false when a failing score appears.
Floating-point rounding
Floating-point rounding arises when a number cannot be stored exactly in binary, affecting arithmetic and equality tests.
Adding 0.1 ten times produces 0.9999999999999999, so an exact loop endpoint can be missed.
For...in loop
A for...in loop visits enumerable property names, which makes it unsuitable as the ordinary value loop for arrays.
On an array it supplies string index names and may also visit added properties that are not elements.
For...of loop
A for...of loop receives each value supplied by an iterable in order, without requiring an explicit numeric counter.
for (const fruit of fruits) reads fruit names directly so the body can process each name.

I

In-place sort
An in-place sort changes the order in the existing array and returns that same array instead of creating an independent one.
After const ordered = scores.sort(...), ordered and scores refer to the same array.
Index
An index identifies a position in an array, with ordinary indexed elements counted from zero through one less than length.
The third element is read with colors[2] because zero-based indexing starts before index one.
Index search
An index search returns a matching position or a no-match marker; indexOf and lastIndexOf use negative one for failure.
[3, 7, 3].lastIndexOf(3) returns 2, pointing to the last matching element.
Index-based traversal
An index-based traversal visits an array through numeric positions, giving control over direction, step size and neighbor access.
A backward traversal starts at arr.length - 1 and decreases the index while it is at least zero.
Infinite loop
An infinite loop keeps repeating without terminating because its execution never reaches an effective exit.
A counter that never changes can leave while (n < 3) printing the same value indefinitely.
Initial value
An initial value gives reduce its starting accumulator and is returned unchanged when the input has no elements to process.
Providing 0 makes an empty sum reduction return zero instead of throwing a TypeError.
Initialization
Initialization sets up a loop's starting state; in a for loop it runs once before the first condition check.
In for (let i = 1; i <= 5; i++), the initialization creates i with the starting value 1.
ISO date string
An ISO date string in fixed-width YYYY-MM-DD form places year, month and day in an order that sorts chronologically as text.
The string "2025-11-02" sorts before "2026-01-20" because the year is compared first.
Iterable
An iterable supplies a sequence of values that operations such as for...of and spread can visit in order.
Arrays and strings are iterable, but spreading the number 5 into an array throws a TypeError.
Iteration
An iteration is one execution of a loop body, occurring after a successful condition check in a counting loop.
Printing the numbers 1 through 5 with one print per body run takes five iterations.

J

Join
Join is an array method that produces one string by placing a chosen separator between the text forms of its elements.
["2026", "03", "15"].join("-") produces the date string "2026-03-15".

L

List formatting
List formatting turns string elements into readable text with separators and connectors chosen for the reader's locale.
Intl.ListFormat can add "and" before the final name in an American English list.
Locale
A locale identifies language or regional conventions used for operations such as text comparison and number formatting.
The locale "sv" places "ä" after "z", while German comparison places it before "z".
LocaleCompare
LocaleCompare is a string method that reports relative text order under locale rules through the sign of its numeric result.
A negative result from a.localeCompare(b, "en") places a before b in that comparison.
Loop condition
A loop condition is the test that decides whether another iteration may run; a false precheck stops the body from running.
With i < 10, reaching i = 10 ends the loop before another body execution.
Loop label
A loop label names a loop so a labeled break or continue can direct control to that enclosing loop.
Writing break outer; at a match can end both loops when the outer loop is labeled outer.

M

Map
Map is an array method that stores callback results in a new array with the same length as the source array.
Mapping distances through km => km * 1000 builds corresponding measurements in meters.
Membership test
A membership test asks whether a value occurs in a collection and reports a boolean instead of a matching position.
drinks.includes("tea") answers whether that exact lowercase string is present in the array.
Method chain
A method chain uses one call's returned value as the receiver of the next call, letting a data-processing sequence read left to right.
A filter-map chain first keeps selected numbers and then transforms only those retained numbers.
Mutation
Mutation changes an existing array's contents or order, making the change visible through every reference to that array.
Calling scores.push(95) mutates scores even when the variable was declared with const.

N

Nested array
A nested array is an array stored as an element inside another array, allowing structures such as rows of values.
In grid[1][0], the first index selects a row and the second selects a value within that row.
Nested loop
A nested loop is a loop inside another loop; its inner sequence runs again for each iteration that reaches it.
A three-row, four-column traversal runs its inner body twelve times when all positions are visited.
Number formatting
Number formatting converts a number to display text using conventions such as the locale's decimal and grouping separators.
Formatting 1234.5 with "de-DE" produces "1.234,5", a string to display after numeric sorting.

O

Off-by-one error
An off-by-one error makes a boundary calculation or loop include one extra position or miss one intended position.
Using i <= arr.length reads one index beyond the last element in an array traversal.

P

Parameter
A parameter is a named input in a function's definition; its position determines which supplied argument it receives.
In a map callback (value, i), the second parameter receives the current element's index.
Predicate
A predicate is a function used as a test; its result decides whether an element matches a condition or should be kept.
The predicate n => n !== null preserves valid zero readings while rejecting null readings.
Push and pop
Push and pop add to and remove from an array's end; push returns the new length, while pop returns the removed element.
A list can append a name with push and later remove that final name with pop.

R

Reduce
Reduce is an array method that carries an accumulator through callback calls and returns the final accumulated result.
A sum reduction starting at zero adds each temperature and returns one numeric total.
Reduction step
A reduction step uses the current accumulator and one element to return the accumulator that the next callback call receives.
A counting step returns either count + 1 or the unchanged count according to the test.
Reference
A reference identifies a shared array so multiple variables can access the same contents without each holding a separate copy.
After const b = a, calling b.push(4) also changes the array read through a.
Rest parameter
A rest parameter gathers a function's remaining supplied arguments into an array; call spread expands values in the opposite direction.
In function total(...nums), nums collects the separate arguments into one array.
Return value
A return value is the result a function sends back to its caller; a block body with no return statement gives undefined.
A map callback with { n * 2; } computes a product but fails to return it for storage.
Reversal
A reversal flips the current sequence from last to first without comparing values to establish numeric or alphabetical order.
Reversing [3, 1, 2] gives [2, 1, 3], which is not a numerically sorted sequence.

S

Shallow copy
A shallow copy creates a new outer array while keeping the same element values, including references to any nested arrays.
Pushing into a row of a spread-copied grid changes the row shared with the original grid.
Shift and unshift
Shift and unshift remove from and add to the start of an array, changing the indexes of the elements that remain.
Using queue.shift() removes the first waiting name and moves the next name to index zero.
Side effect
A side effect is an action a function performs beyond providing its returned value, such as printing or changing shared data.
A forEach callback can print a name even though the method itself returns undefined.
Slice
Slice is an array method that returns a shallow copy of a range without editing the source, excluding the ending index.
values.slice(1, 3) copies the values at indexes one and two into a new array.
Some
Some is an array method that returns true when at least one callback test passes and stops as soon as that success is found.
Checking whether any score is below fifty returns true at the first failing score.
Splice
Splice is an array method that removes or inserts elements in place and returns an array of the removed elements.
The call days.splice(2, 0, "Wed") inserts a day at index two without removing an existing day.
Split
Split is a string method that creates an array of text pieces by cutting at occurrences of a specified separator.
Splitting "4,8,15" on a comma yields three strings that still need conversion for numeric addition.
Spread syntax
Spread syntax expands an iterable's values into an array literal or into separate arguments at a function call.
The expression [...first, ...second] places the values from both arrays into a new outer array.
Stable sort
A stable sort preserves the original relative order of elements that the comparison function treats as equal.
Words of equal length keep their earlier order when sorted using only a length comparison.

T

Trace table
A trace table records changing values at successive execution steps so a loop's behavior can be followed and checked.
Columns for the current reading and running sum show exactly which iteration first produces a wrong total.

U

Update
An update changes the loop's state between iterations; a for loop performs its header update after its body.
The update i += 5 makes the next counter value five greater than the previous one.

W

While loop
A while loop checks its condition before every iteration and repeats while that condition is truthy, possibly running zero times.
A growth calculation uses while (balance < 1500) to repeat until the target is reached.

About this lesson

By StudeliReport a mistake

Make your own Study Materials

Turn your notes, slides and documents into Study Guides, Practice Questions, Flashcards and 6 more tools.

Get Started