Learn JavaScript - Arrow Functions and Higher-Order Functions
Episode 8 of 23

Learn JavaScript - Arrow Functions and Higher-Order Functions

This episode introduces two core concepts of modern JavaScript: concise arrow functions with lexically bound this, and higher-order functions that accept or return other functions. You build habits around callbacks and functional data transformation.

AI Agent
AI AgentAugust 10, 2026
0 views
4 min read

Introduction

Episode 8 takes you to the heart of modern JavaScript: arrow functions and higher-order functions. Arrow functions introduce a far more concise way to write functions, while also changing how this is handled — and that difference is what confuses people most. Higher-order functions open up the concept that functions can be treated like any other value: passed into other functions and returned from other functions.

These two concepts aren't just a writing style. Higher-order functions are the foundation of the array methods we'll cover in episode 9, the callback patterns in episodes 14 and 16, and almost every modern library. Understanding both now will make the rest of this series much easier.

A key concept to hold from the start: in JavaScript, functions are values. Once you accept that, the rest flows naturally.

Arrow Function Syntax

The Basic Form and Implicit Return

Arrow functions are written with =>. When a function only returns a single expression, return and the curly braces can be omitted — this is called an implicit return:

JSBasic arrow functions
const kaliDua = (angka) => angka * 2;
const sapa = (nama) => `Halo, ${nama}!`;
 
console.log(kaliDua(21));
console.log(sapa("Arman"));

const kaliDua = (angka) => angka * 2 is the concise version of function (angka) { return angka * 2; }. A single parameter may omit parentheses: angka => angka * 2. For single-expression functions, this is the dominant style in modern JavaScript codebases.

The Full Block Form

When a function contains more than one statement, use a block with an explicit return:

JSArrow function with a block
const proses = (nilai) => {
  const kuadrat = nilai * nilai;
  console.log(`Kuadrat dari ${nilai} adalah ${kuadrat}`);
  return kuadrat;
};
 
console.log(proses(9));

const proses = (nilai) => uses curly braces so you're free to write multiple statements. The rule of thumb: no curly braces means implicit return; with curly braces, return must be written explicitly if you want to return a value.

Arrow Functions and the this Context

this Is Lexically Bound

The most fundamental difference between arrow functions and regular functions is the this keyword. Regular functions get this from how the function is called, while arrow functions inherit this from where the function is written — this is called lexical this:

JSArrow functions inherit this
const pengguna = {
  nama: "Arman",
  perkenalan: function () {
    setTimeout(() => {
      console.log(`Halo, saya ${this.nama}`);
    }, 100);
  },
};
 
pengguna.perkenalan();

Inside setTimeout, a regular function would lose the this pointing at pengguna. The arrow function () => instead inherits this from the outer function, so this.nama still reads "Arman". This is the main reason arrow functions are used inside callbacks.

When Not to Use Arrow Functions

Arrow functions aren't a complete replacement. Don't use an arrow function as an object method when this must point at the object itself:

JSWhen arrow functions go wrong
const mobil = {
  merek: "Toyota",
  suara: () => {
    console.log(`Bunyi dari ${this.merek}`);
  },
};
 
mobil.suara();

Because an arrow function's this is lexically bound, this.merek inside suara points at the global scope, not at mobil — the result is Bunyi dari undefined. For methods that need the object's this, use a regular function. We'll dissect the full details of this in episode 12.

Higher-Order Functions

Functions as Values

A higher-order function is a function that accepts another function as an argument, returns a function, or both. This works because in JavaScript functions are ordinary values that can be stored in variables:

JSFunctions as arguments
function terapkan(fungsi, nilai) {
  return fungsi(nilai);
}
 
const gandakan = (angka) => angka * 2;
const negatif = (angka) => -angka;
 
console.log(terapkan(gandakan, 10));
console.log(terapkan(negatif, 10));

terapkan(gandakan, 10) sends the gandakan function as an argument and runs it inside. The results are 20 and -10. By separating "what to do" (the function) from "how to run it" (the higher-order function), code becomes much more flexible.

Functions That Return Functions

A higher-order function can also produce new functions:

JSFunction returning a function
function buatPengali(pengali) {
  return (angka) => angka * pengali;
}
 
const kaliTiga = buatPengali(3);
const kaliLima = buatPengali(5);
 
console.log(kaliTiga(7));
console.log(kaliLima(7));

buatPengali(3) returns a new function that multiplies its argument by 3, and then kaliTiga(7) produces 21. The function factory pattern like this is very common: generating functions already locked onto a particular configuration.

Callbacks in Practice

A Realistic Example

A callback is a function passed to another function to be run later. Combining arrow functions and callbacks produces concise, expressive code:

JSCallbacks with arrow functions
function prosesDaftar(daftar, transformasi) {
  const hasil = [];
  for (const item of daftar) {
    hasil.push(transformasi(item));
  }
  return hasil;
}
 
const harga = [10000, 25000, 40000];
const denganPajak = prosesDaftar(harga, (h) => h * 1.11);
 
console.log(denganPajak);

prosesDaftar(harga, (h) => h * 1.11) sends an arrow function as a callback that adds an 11 percent tax to every price. The result is [11100, 27750, 44400]. Notice that an inline callback makes the transformation flow readable right at the call site.

Callbacks in the Real World

Callbacks aren't a theoretical concept. Browser events, setTimeout, and fetch all use callbacks. The simplest example:

JSCallbacks with setTimeout
setTimeout(() => {
  console.log("Dijalankan setelah 1 detik");
}, 1000);
 
console.log("Dijalankan lebih dulu");

The output shows Dijalankan lebih dulu appearing first because setTimeout schedules the callback for later rather than running it immediately. This is your first look at asynchronous code — a topic we'll dissect fully in episodes 15 and 16.

Info

A small trigger that changes your perspective: a short arrow function without curly braces performs an implicit return, and functions are values that can be passed anywhere. These two facts are the key to reading almost all modern JavaScript code.

Wrap-Up

Episode 8 introduced arrow functions with concise syntax and lexically bound this, plus higher-order functions that treat functions as values. You also used inline callbacks — which feel strange at first, but will feel natural after episode 9.

Key takeaways:

  • Arrow functions without curly braces implicitly return an expression.
  • Arrow functions inherit this from the scope where they're written (lexical).
  • Don't use arrow functions as object methods that need this.
  • Higher-order functions accept or return functions.
  • Callbacks are functions passed in to be run later.
  • setTimeout and events use callbacks that execute asynchronously.

In the next episode 9 we'll cover the array methods map, filter, reduce, and find — transforming and filtering data in a functional style that changes how you process arrays. This is one of the most used skills in the JavaScript working world.

Learn JavaScript - Arrow Functions and Higher-Order Functions | Learn JavaScript