Glossary
Array Methods

JavaScript Array Methods

In the Making a Trail section of the lerp tutorial, a handful of standard JavaScript array methods come up. None of these are p5-specific — they work the same way in any JavaScript context. Here's a quick look at the ones used.

push()

push() adds one or more items to the end of an array and returns the new length.

let trail = []
trail.push('a')  // trail is ['a']
trail.push('b')  // trail is ['a', 'b']

In the trail sketch, push() is how we fill the array with nodes during setup:

for (let i = 0; i < count; i++) {
  trail.push(new TrailNode(width/2, height/2, 60, speed))
}

forEach() and map()

Both methods loop over every item in an array and run a callback function on each one. The difference is what they return:

  • forEach() runs the callback and returns nothing.
  • map() runs the callback and returns a new array of the callback's return values.
let numbers = [1, 2, 3]
 
numbers.forEach(n => console.log(n))
// logs 1, then 2, then 3 — no return value
 
let doubled = numbers.map(n => n * 2)
// doubled is [2, 4, 6]
// numbers is still [1, 2, 3]

In the trail sketches, both forEach() and map() are used to iterate over nodes. In practice, either works for updating or drawing since we're not using the return values. The callback also receives the current index as a second argument, which comes in handy for the color gradient:

trail.slice().reverse().map((node, i) => {
  fill(105 + i/trailSize*100, 0, 64 + i/trailSize*64)
  node.display()
})

slice()

slice() returns a shallow copy of an array without modifying the original. Called with no arguments, it copies the whole thing.

let original = [1, 2, 3]
let copy = original.slice()
 
copy.push(4)
// copy    is [1, 2, 3, 4]
// original is [1, 2, 3] — unchanged

reverse()

reverse() reverses an array in place. That means it modifies the original array directly and returns it.

let items = ['a', 'b', 'c']
items.reverse()
// items is now ['c', 'b', 'a']

Why slice() comes before reverse()

The in-place behavior of reverse() is the reason slice() appears first in the trail sketch. If we called trail.reverse() directly inside the draw loop, the trail array would be permanently flipped — and on the next frame, the update loop would process nodes in reverse order. The chain would break.

Using slice() first creates a temporary copy to reverse, leaving the original untouched:

trail.slice().reverse().forEach(node => node.display())
//   ↑ copy         ↑ reverse the copy, not trail itself

You can see the difference draw order makes here. Both rows contain the same five overlapping circles, but the left draws them front-to-back (index 0 first, buried at the bottom) and the right draws them back-to-front (index 0 last, sitting on top):

On the left, each new circle lands on top of the previous one — so index 0 ends up at the bottom of the stack. On the right, the loop is reversed, so index 0 is drawn last and sits on top. In the trail sketch, index 0 is the head — the circle closest to the mouse — so reversed draw order is what makes it sit in front of the rest of the trail.