Originally published on php-to-js.learnio.dev — part of the PHP to JavaScript course. View this lesson on the original site.

You write the function; something else chooses when it runs

Passing a function as an argument is normal in both languages. The habit to build is asking: who calls this, and before or after the next line?

PHP habit: synchronous callables

<?php
$scores = [88, 92, 75];
usort($scores, fn ($a, $b) => $b <=> $a);
// comparator runs during usort — before the next line

array_map(fn ($n) => $n * 2, [1, 2, 3]);

The host (usort, array_map) calls your function immediately while the current code path is still running.

JavaScript equivalent: sync vs async hosts

const scores = [88, 92, 75];
scores.sort((a, b) => b - a);
console.log(scores); // [92, 88, 75] — done on this line

console.log('A');
setTimeout(() => console.log('B'), 0);
console.log('C');
// A, C, then B
Who calls you PHP example JavaScript example When
Sync host usort, array_map sort, map, filter Before the next line after the call
Async host Queue job, event listener (later) setTimeout, addEventListener After current work or on an event

How to read registration code

button.addEventListener('click', saveOrder);
// not saveOrder() — you pass the function; the browser calls it on click

Same idea as registering a Laravel event listener: you hand over behaviour; the framework invokes it later.

Try it

Use the amber Try it panel below. Click Run.

function runSync(fn) {
  console.log('sync: before');
  fn();
  console.log('sync: after');
}

function runAsync(fn) {
  console.log('async: schedule');
  setTimeout(fn, 0);
  console.log('async: after schedule');
}

runSync(() => console.log('  callback (sync)'));
runAsync(() => console.log('  callback (async)'));

Sync callback runs between before/after. Async callback runs after both lines.

From PHP to JavaScript — Control Flow, Functions, and Scope