Explain Codes LogoExplain Codes Logo

Pass a JavaScript function as parameter

javascript
function-passing
callback-functions
async-programming
Nikita BarsukovbyNikita Barsukov·Aug 31, 2024
TLDR

In JavaScript, you can pass a function as an argument to another function as you would any variable. Here's a quick and simple example:

function greet(name) { // A plain function console.log(`Hello, ${name}!`); } function runCallback(cb) { // A higher-level function cb('Alice'); // Executing the passed function } runCallback(greet); // Here you go! Prints: Hello, Alice!

Here, the runCallback function receives greet as a callback (cb) and executes it using 'Alice' as the name. Make no mistakes dear coder, this is no wizardry, it's modulo mercantile JavaScript!

Code-wise function handling

Passing by Reference, not by a Broomstick!

JavaScript allows passing a function by reference. It meanly heartlessly discards the magical parentheses. Why? So the function is not called right then and there! Here, have a look:

function add(a, b) { // A wise old function, adds stuff return a + b; } function runWithValues(fn, val1, val2) { // A much younger function, full of life return fn(val1, val2); // Running the old function, helping it cross the road } console.log(runWithValues(add, 5, 3)); // Running the show. Prints: 8

Check before you Wreck!

Invoking a non-existent function or a non-function (oops!) can cause a TypeError. A safety check using typeof can save the day!

function safeInvoke(callback) { // A safety-obsessed function if (typeof callback === 'function') {// Checking if it's safe to proceed callback(); // The coast is clear. Go, go, go! } } safeInvoke(greet); // SAFE! Here's a cookie 🍪!

Scope and Butter

Want to retain scope while passing callbacks with arguments? Use object binding methods like .bind(). It's as smooth as butter.

function notify() { // A notifier function console.log('Notification sent!'); // Ding dong! You've got mail! } function delayAndRun(task) { // The procrastinator function setTimeout(task, 1000); } delayAndRun(notify.bind(this)); // Notify, after a well-deserved 1s procrastination!

Expert Function Hacks

Argumentative Callbacks

Need to call a callback with specific arguments? .apply() or .call() are your friends. They accept arguments aplenty!

function greetUser(user) { // The welcoming committee console.log(`Welcome, ${user}!`);// Rolling out the red carpet } function runCallbackWithUser(cb, user) { // The function delegation service cb.apply(null, [user]); } runCallbackWithUser(greetUser, 'Bob'); // Output: Welcome, Bob! We've been expecting you.

Anonymous Shields

To protect the scope of arguments when a callback calls, use an anonymous function. It's the medieval shield you didn't know you needed.

function processData(data, cb) { // The industrious factory function // Doing something with data... cb(data); // Calling up the boss } processData({ id: 1 }, function(dataset) { // The new improved, vitamin-enriched callback console.log(`Processing data: ${JSON.stringify(dataset)}`); });

Asynchronous Function-sharing

When dealing with asynchronous tasks such as server calls or event loops, function passing becomes a life-saver.

fetch('/api/data') // An API call .then(response => response.json()) // JSONify the response .then(data => { // Pass the data console.log(data); // Voila! });

Pitfall Dodging

To dodge the null trap or an unwanted undefined, make sure to check if the function you're calling isn’t one of those. Or, make it default to a noop (no operation) function.

function invokeIfFunction(callback = () => {}) { // Operations HQ if (typeof callback === 'function') { // Safety first! callback(); // All clear, proceed! } } invokeIfFunction(); // Does nothing, not a single squeak.