Functions are reusable blocks of code. You define them once and call them whenever you need that logic. If you’ve written def in Python, you already understand the concept — JavaScript just wraps it differently.
The structure is identical — keyword, name, parameters, body, return. JavaScript uses function instead of def, curly braces instead of indentation, and camelCase instead of snake_case.
Functions return undefined by default. If you want a value back, you need an explicit return statement.
Copy
function add(a, b) { return a + b; // Returns the sum}function logMessage(message) { console.log(message); // No return — returns undefined}const result = add(5, 3);console.log(result); // 8
return also exits the function immediately. Code after return never runs.
Copy
function checkAge(age) { if (age < 18) { return "Too young"; } return "Welcome"; // Only runs if age >= 18}console.log(checkAge(15)); // "Too young"console.log(checkAge(25)); // "Welcome"
You can also create functions by assigning them to variables:
Copy
const multiply = function(a, b) { return a * b;};console.log(multiply(4, 5)); // 20
This is called a function expression. The function doesn’t have its own name — it’s stored in the variable multiply.
Function declarations are “hoisted” — you can call them before they appear in your code. Function expressions are not. For now, stick with function declarations. You’ll use function expressions more when you learn arrow functions next.
# Almost identical in Pythondef apply_operation(a, b, operation): return operation(a, b)def add(x, y): return x + ydef subtract(x, y): return x - yprint(apply_operation(10, 3, add)) # 13print(apply_operation(10, 3, subtract)) # 7
You’ll use this pattern constantly. Array methods like .map(), .filter(), and .forEach() all take functions as arguments. React event handlers work the same way.
Get comfortable with passing functions as arguments. It’s one of the most common patterns in JavaScript and React. You’ll see it everywhere: array.map(myFunction), button.addEventListener("click", myFunction), <button onClick={myFunction}>.
function sayHello() { return "Hello!";}// Calling the function — runs it, gives you the resultconsole.log(sayHello()); // "Hello!"// Referencing the function — passes the function itselfconsole.log(sayHello); // [Function: sayHello]
With parentheses () you call the function. Without parentheses, you reference it. This matters when passing functions to event handlers or array methods — you pass the reference, not the result.
Copy
// ✅ Correct: Pass the function referencebutton.addEventListener("click", handleClick);// ❌ Wrong: This CALLS handleClick immediatelybutton.addEventListener("click", handleClick());
If your function computes a value but doesn’t return it, you get undefined. This is one of the most common bugs in JavaScript — especially for Python developers, since Python returns None explicitly.
Calling a function reference instead of passing it
Copy
// ❌ Wrong: Calls immediately, passes the return valuesetTimeout(doSomething(), 1000);// ✅ Correct: Passes the function, called latersetTimeout(doSomething, 1000);
When passing a function as an argument, don’t add () unless you want it to run immediately. This trips up everyone at first — especially in React’s onClick handlers.
Semicolon after function declarations
Copy
// Function declarations — no semicolon neededfunction greet(name) { return `Hello, ${name}!`;}// Function expressions — semicolon after the assignmentconst greet = function(name) { return `Hello, ${name}!`;};
Function declarations don’t end with a semicolon (they’re statements). Function expressions do (they’re assignments). This is a minor style point — Prettier handles it automatically if you have it set up.
You know how to write and call functions. JavaScript has a shorter, more modern syntax for functions called arrow functions — you’ll use them everywhere in React.