JavaScript: The Complete Language Guide
Chapter 3 / 7· 22 min read· 0 cards

Functions, Arrow Functions and Scope

Package logic into reusable functions, master the modern arrow syntax, and understand scope and closures.

Functions: reusable blocks of logic

Functions are the heart of JavaScript. A function packages a piece of logic you can run whenever you need it. The traditional way to declare one uses the function keyword:

function greet(name) {
    return `Hello, ${name}!`;
}

console.log(greet("Mehul"));   // Hello, Mehul!
console.log(greet("Riya"));    // Hello, Riya!

The names in the parentheses are parameters — placeholders for the values you pass in. return sends a value back to whoever called the function, so you can store it, print it, or use it further. A function that doesn't return anything gives back undefined.


Arrow functions: the modern syntax

Modern JavaScript has a shorter, extremely common way to write functions — the arrow function. You'll see these everywhere, so learn to read and write them comfortably:

// Traditional
function add(a, b) {
    return a + b;
}

// Arrow function — same thing, shorter
const add = (a, b) => {
    return a + b;
};

// Even shorter: single expression, implicit return (no braces, no 'return')
const square = x => x * x;

console.log(add(3, 4));    // 7
console.log(square(5));    // 25

The arrow => replaces the function keyword. When the body is a single expression, you can drop the braces and the return — the value is returned automatically. Arrow functions are especially popular for the small functions you pass to array methods and event handlers, which you'll see shortly. Both styles do the same core job; modern code uses arrows heavily.


Default parameters

You can give parameters default values, used when the caller leaves them out:

const greet = (name, greeting = "Hello") => {
    return `${greeting}, ${name}!`;
};

console.log(greet("Mehul"));            // Hello, Mehul!
console.log(greet("Riya", "Welcome"));  // Welcome, Riya!

Scope: where variables live

Scope determines where a variable is accessible. A variable declared inside a function exists only inside that function — this is local scope, and it's a good thing, because it stops different functions from interfering with each other's variables:

function calculate() {
    let secret = 42;       // local — exists only inside calculate
    return secret;
}

calculate();
// console.log(secret);    // ERROR — 'secret' doesn't exist out here

Variables declared with let and const are also block-scoped — they exist only within the nearest { } braces, like inside an if or a loop. This predictable scoping is one reason let/const replaced the old var, which had confusing scope rules.


Functions are values (a JavaScript superpower)

Here's something that makes JavaScript special: functions are values, just like numbers or strings. You can store a function in a variable (you've been doing this with arrow functions), pass a function into another function, and return a function from a function. A function passed to another function is called a callback:

// A function that takes another function as an argument
function repeat(times, action) {
    for (let i = 0; i < times; i++) {
        action(i);   // call the passed-in function
    }
}

repeat(3, (n) => {
    console.log(`Iteration ${n}`);
});
// Iteration 0
// Iteration 1
// Iteration 2

This idea — passing functions as arguments — is everywhere in JavaScript. It powers array methods, event handling, and asynchronous code. It feels strange at first, but it's the source of much of JavaScript's flexibility and elegance.


A glimpse of closures

One more powerful idea worth meeting: a function "remembers" the variables from where it was created, even after that outer function has finished. This is called a closure:

function makeCounter() {
    let count = 0;
    return () => {
        count++;          // remembers and updates 'count'
        return count;
    };
}

const counter = makeCounter();
console.log(counter());   // 1
console.log(counter());   // 2
console.log(counter());   // 3

The inner arrow function keeps access to count even after makeCounter has returned — each call remembers and increments it. Closures power a lot of advanced JavaScript patterns. You don't need to master them now, but recognising the concept will serve you well. Next, we'll explore arrays and the powerful methods that make JavaScript so good at handling lists of data.

Reading mode · scroll to read at your own pace

Finished "Functions, Arrow Functions and Scope"?

Mark this chapter complete so you can pick up exactly where you left off. Your progress saves locally — sign in to sync across devices.

Was this chapter clear?

Try it yourself — open the Code Playground15+ languages — Python, JavaScript, Java, C++, SQL & more — full IDE-style editor, instant run. Your code is auto-saved per language.