Skip to content

JavaScript Functions

A JavaScript function is a reusable block of code designed to perform a specific task. Functions are executed when “something” invokes (calls) them.

Functions are a fundamental building block in JavaScript, enabling modularity, reusability, and abstraction.

There are several ways to define functions in JavaScript:

1. Function Declaration (or Function Statement):

Section titled “1. Function Declaration (or Function Statement):”

Defined with the function keyword, followed by a name, a list of parameters in parentheses (), and a block of code in curly braces {}.

function greet(name) {
return `Hello, ${name}!`;
}
// Function declarations are hoisted, meaning they can be called before they are defined in the code.

A function can also be defined as part of an expression, typically by assigning it to a variable. The function can be named or anonymous.

// Anonymous function expression
const add = function(a, b) {
return a + b;
};
// Named function expression (name 'multiply' is mainly for debugging/recursion within the function)
const multiply = function multiply(x, y) {
return x * y;
};
// Function expressions are not hoisted in the same way as declarations.
// You must define them before you can call them.

ES6 introduced a more concise syntax for writing functions, known as arrow functions.

const subtract = (a, b) => {
return a - b;
};
// If the function has only one statement and returns a value, you can omit curly braces and 'return'
const square = x => x * x;
// If there are no parameters, use empty parentheses
const sayHi = () => console.log("Hi!");
// Arrow functions have some key differences from traditional functions,
// notably their handling of the 'this' keyword and the 'arguments' object (they don't have their own).

Function Parameters and Arguments:

  • Parameters are the names listed in the function definition (e.g., name in greet(name)).
  • Arguments are the actual values passed to the function when it is invoked (e.g., greet("Alice"), “Alice” is the argument).

Inside the function, parameters behave like local variables.

The code inside a function executes when the function is invoked. This typically happens by using the function’s name followed by parentheses () containing any arguments.

console.log(greet("Bob")); // Invokes the greet function, output: "Hello, Bob!"
console.log(add(5, 3)); // Invokes the add function, output: 8
square(4); // Invokes square, returns 16

Functions can be invoked in various contexts:

  • Directly in code.
  • When an event occurs (e.g., a user clicks a button).
  • Automatically (self-invoked functions).
  • As methods of objects.

When JavaScript reaches a return statement, the function stops executing.

The value specified after return is “returned” to the caller. If return is used without a value, or if the end of the function is reached without a return statement, the function implicitly returns undefined.

function calculateArea(width, height) {
if (width <= 0 || height <= 0) {
console.error("Width and height must be positive.");
return; // Implicitly returns undefined
}
return width * height; // Returns the calculated area
}
let area1 = calculateArea(10, 5); // area1 will be 50
let area2 = calculateArea(-2, 5); // area2 will be undefined, error logged
  • Code Reusability: Define code once and use it multiple times.
  • Modularity: Break down complex problems into smaller, manageable pieces.
  • Abstraction: Hide complex implementation details and provide a simple interface.
  • Organization: Make code easier to read, understand, and maintain.

Example: Converting Fahrenheit to Celsius.

function toCelsius(fahrenheit) {
return (5 / 9) * (fahrenheit - 32);
}
let temp1 = toCelsius(32); // 0
let temp2 = toCelsius(212); // 100
// document.getElementById("demo").innerHTML = `32°F is ${temp1}°C`;

Accessing a function name without () refers to the function object itself. Adding () invokes it.

function toCelsius(fahrenheit) {
return (5 / 9) * (fahrenheit - 32);
}
// Referring to the function object
// const converter = toCelsius;
// document.getElementById("output1").innerHTML = converter;
// Output would show the function's string representation, e.g., "function toCelsius(fahrenheit) { ... }"
// Invoking the function
// const tempInCelsius = toCelsius(68);
// document.getElementById("output2innerHTML = tempInCelsius;
// Output would be the result, e.g., 20

In JavaScript, functions are “first-class citizens.” This means they can be treated like any other value:

  • Assigned to variables (as shown with function expressions).
  • Passed as arguments to other functions (callbacks).
  • Returned as values from other functions (higher-order functions).

This flexibility is a powerful feature of JavaScript.

function applyOperation(a, b, operation) {
return operation(a, b);
}
const sumResult = applyOperation(5, 2, add); // 'add' function passed as argument
console.log(sumResult); // Output: 7
const productResult = applyOperation(5, 2, (x, y) => x * y); // Arrow function passed
console.log(productResult); // Output: 10

A closure is a function that has access to its outer (enclosing) function’s scope, even after the outer function has returned. This means a closure can “remember” and access variables and arguments of its outer function.

function createGreeter(greeting) {
return function(name) { // This inner function is a closure
console.log(`${greeting}, ${name}!`);
};
}
const greetHello = createGreeter("Hello");
const greetHi = createGreeter("Hi");
greetHello("Alice"); // Output: Hello, Alice!
greetHi("Bob"); // Output: Hi, Bob!

Closures are a powerful concept used for data privacy, creating factory functions, and in many advanced JavaScript patterns. (More details in a dedicated closures section).