DataLens

Functions and arrow functions

Package logic into reusable functions with parameters, defaults and return values, write compact arrow functions, and pass functions around as values.

Level: Foundations · 8 min read

Practise this module

The questions for this lesson run in your browser and check your answer straight away.

The idea

A function is a named, reusable piece of logic: give it inputs, it gives back an output. You've used built-in ones already (console.log, Math.round, Number). Writing your own is how you stop repeating code and start building programs out of small, understandable pieces, exactly like functions in Python.

Declaring and calling

Toko Kita shows prices with 11% VAT included, and that calculation is needed on the product page, in the cart and at checkout. Rather than writing price * 1.11 in all three places, you give the calculation a name once, then use it wherever it's needed:

function addVat(price) {
  return Math.round(price * 1.11);
}

console.log(addVat(95000));
console.log(addVat(250000));
105450
277500

Parameters and defaults

Shipping costs 12000 per kilo for most orders, but sometimes a different rate applies, like express delivery. A default value lets a function use the usual rate unless you say otherwise:

function shippingCost(weightKg, perKg = 12000) {
  return weightKg * perKg;
}

console.log(shippingCost(2));
console.log(shippingCost(2, 15000));
console.log(shippingCost());
24000
30000
NaN

Arrow functions

Lots of functions are tiny one-liners, and writing function, the curly braces and return for each one gets wordy. Modern JavaScript has a shorter way to write them, called arrow functions, and you'll see them everywhere:

const addVat = (price) => Math.round(price * 1.11);
const formatRupiah = (amount) => "Rp " + amount.toLocaleString("id-ID");
const greet = () => "Selamat datang!";
const lineTotal = (price, qty) => {
  const subtotal = price * qty;
  return subtotal > 500000 ? subtotal * 0.95 : subtotal;
};

console.log(formatRupiah(addVat(95000)));
console.log(greet());
console.log(lineTotal(200000, 3));
Rp 105.450
Selamat datang!
570000

Arrow functions and function declarations behave the same for everyday use. The differences (this and hoisting) come up in module 9; for now, use arrows for short helpers and callbacks, and either style for named functions.

Functions are values

A function can be stored in a variable, put in an object, or passed to another function. That last one is everywhere in JavaScript:

const prices = [95000, 120000, 45000];

function applyToAll(values, fn) {
  const result = [];
  for (const value of values) {
    result.push(fn(value));
  }
  return result;
}

console.log(applyToAll(prices, addVatTo));

function addVatTo(price) {
  return Math.round(price * 1.11);
}

console.log(applyToAll(prices, (p) => p / 1000 + "k"));
[105450, 133200, 49950]
["95k", "120k", "45k"]

A function passed to another function is called a callback. Event handlers (module 6), array methods like map and filter (module 8) and timers all take callbacks.

Notice that addVatTo was used before its declaration. function declarations are hoisted: JavaScript makes them available throughout their scope. Arrow functions stored in const aren't: using one before its line is an error.

Rest parameters

Sometimes you don't know in advance how many values a function will get. A cart total might be two items or twenty. A rest parameter collects however many arguments are passed into one array:

function total(...amounts) {
  let sum = 0;
  for (const amount of amounts) sum += amount;
  return sum;
}

console.log(total(95000, 120000, 45000));
console.log(total());
260000
0

...amounts collects all the arguments into an array, like *args in Python.

Key idea

Functions take parameters (with optional defaults) and return a value. Arrow functions ((x) => x * 2) are the compact form, with implicit return for single expressions. Functions are values: store them, and pass them as callbacks.

Why this matters for clean code

Good functions are small, named for what they do, and pure where possible: same inputs, same output, no hidden side effects. addVat(price) can be tested in one line and reused anywhere. A 200-line event handler that calculates VAT inline can't. Most of the rest of this track is about splitting code into functions like these.

Recap

Practise this module

The questions for this lesson run in your browser and check your answer straight away.

Next: Arrays and objects →