[JS] JavaScript Functions: myFunc vs myFunc() Explained Simply

[JS] JavaScript Functions: myFunc vs myFunc() Explained Simply

What you can expect from this post?

When I was learning JavaScript, one thing kept confusing me:

We often need to pass a function into another function — like setTimeout or addEventListener — but sometimes we add parentheses () after the function name, and sometimes we don’t. How do we know when to use them?

In this post, I’ll explain why functions with or without parentheses behave differently, and how you can decide which to use.


In JavaScript, Functions Are First-Class Citizens

In JavaScript, functions are first-class citizens. That means:

Functions can be treated like any other value.

So just like numbers or strings, you can:

  • Assign a function to a variable
  • Pass a function as a parameter
  • Return a function from another function
  • Store a function inside an array or object

Today, we’ll focus on passing functions as arguments — and more specifically, when to use () and when not to.

Do You Want to Execute the Function Now or Later?

Let’s look at a classic example:

button.addEventListener('click', handleClick);   // Correct
button.addEventListener('click', handleClick()); // Wrong

What’s going on here?

  • handleClick — this passes the function itself to addEventListener, which can execute it later when the click happens.
  • handleClick() — this immediately executes the function and passes the result of that execution to addEventListener.

But addEventListener expects a function to call later, not the result of a function.

You can think of it this way:

You write... It means...
handleClick “Here is the function. Call it later when the event fires.”
handleClick() “Run this function now, and here’s the result.”

To put it simply, if we need this function to be executed right away, we have to add () as below:

function sayHi() {
  console.log("Hi!");
}

sayHi(); // I want to print out "Hi!" right now

However, if I just want to pass functions as callback functions for other methods to use later, we shouldn’t add ()

function sayHi() {
  console.log("Hi!");
}
setTimeout(sayHi, 1000); // Correct, sayHi wil be executed after one second
setTimeout(sayHi(), 1000); // Wrong, sayHi function will be executed right away and pass results wihch is "undefined" to setTimeout

Why is this wrong?

  • sayHi() is executed immediately, printing "Hi!" right away
  • Since sayHi() doesn't return anything, it returns undefined
  • So what you're really doing is:
setTimeout(undefined, 1000);

Which doesn't work — setTimeout needs a function to call later, but you're giving it undefined.


What If I Want to Pass Arguments?

Sometimes, you want to pass a function with arguments, like this:


setTimeout(sayHi("Amy"), 1000); // Wrong, his still runs immediately

In this case, wrap it in an arrow function:

setTimeout(() => sayHi("Amy"), 1000); // This works!

Why does this work?

Because () => sayHi("Amy") is a new function. You're passing this function to setTimeout, and sayHi("Amy") will only run when that arrow function gets called — in this case, after one second.


Arrow Functions Are Your Friend

Arrow functions are especially useful when you:

  • Want to pass a function with parameters
  • Want to add extra logic inside a callback
  • Need to preserve this context
button.addEventListener('click', () => {
  console.log("Button clicked!");
  handleClick("Amy");
});

Conclusion

Understanding when to use () with functions in JavaScript comes down to one key idea:

Do you want to run the function now, or pass it to be run later?

If you just remember that functions are values, and that adding () executes them immediately, you’ll avoid a lot of confusion — especially when working with callbacks like setTimeout, addEventListener, or map.