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