Soal 1Setelah kamu menjalankan prices.map((price) => price * 2), apa yang terjadi pada prices yang asli?
map dan filter — Mengubah atau Menyaring Array
Pelajari map yang mengubah tiap element dan filter yang hanya menyisakan element yang cocok, lengkap dengan chaining dan argument index.
Saat menghitung harga termasuk pajak dari daftar menu atau memilih produk yang stoknya masih ada, kamu sering menulis pola yang sama: deklarasikan array kosong, lalu panggil push di dalam forEach.
Artikel ini membahas map, yang mengubah element, dan filter, yang hanya menyisakan element yang memenuhi kondisi.
Mengubah Tiap Element Menjadi Array Baru — map
Misalnya kamu butuh daftar harga menu kafe yang sudah ditambah pajak. Hasilnya berupa array dengan urutan yang sama seperti 3 item aslinya, hanya harganya yang berganti. Menghitung harga satu per satu bisa kamu tulis dengan forEach, tapi untuk mengumpulkan hasilnya kamu harus menyiapkan array sendiri dan mengurusnya sampai loop selesai.
Method array map (method yang meneruskan tiap element ke callback lalu mengembalikan array baru berisi return value-nya secara berurutan) mengurus dua hal sekaligus: menyiapkan array penampung hasil dan menjalankan perulangannya. Function yang kamu berikan cukup berisi cara mengubah 1 element, lalu mengembalikan hasilnya.
const menuItems = [
{ name: "Kopi Tubruk", price: 480 },
{ name: "Caffe Latte", price: 540 },
{ name: "Cheesecake", price: 620 },
];
// Function-nya cukup mengubah 1 item
const toTaxIncluded = (item) => Math.floor(item.price * 1.1);
// toTaxIncluded dipanggil sekali untuk tiap element, dan return value-nya mengisi array baru
const taxIncluded = menuItems.map(toTaxIncluded);
console.log(taxIncluded.join(", ")); // 528, 594, 682
console.log(taxIncluded.length); // 3
console.log(menuItems.length); // 3
taxIncluded dengan urutan yang sama seperti element aslinya. map tidak mengubah jumlah element, hanya value-nya.map hanya menyerahkan element ke callback satu per satu, lalu menaruh value yang kembali ke array baru. Karena itu, jumlah element-nya tidak mungkin berubah. Untuk menyaring array, yang memang mengubah jumlah element, kamu butuh method lain.
forEach Tidak Memberikan Return Value
forEach hanya memanggil function yang kamu berikan dan tidak mengumpulkan return value-nya. Yang dikembalikan selalu undefined, jadi kalau kamu menulis const list = menuItems.forEach(toTaxIncluded);, list tetap undefined. Kalau kamu ingin hasilnya berupa array, pakai map.
Menyisakan Element yang Cocok Saja — filter dan Jumlah Element yang Tersisa
Misalnya kamu ingin menampilkan hanya buku yang stoknya masih ada. map tidak mengubah jumlah element, jadi tidak bisa dipakai untuk membuang buku yang stoknya habis, dan kamu kembali lagi menulis if di dalam forEach lalu memanggil push.
filter (method yang mengembalikan array baru yang hanya berisi element yang membuat callback mengembalikan true) menangani penyaringan seperti ini. Function yang kamu berikan menerima element, lalu mengembalikan boolean yang menentukan apakah element itu disimpan atau tidak.
const books = [
{ title: "SQL Praktis", stock: 0 },
{ title: "Dasar Jaringan", stock: 5 },
{ title: "Linux Bergambar", stock: 2 },
];
// Buat function yang mengembalikan boolean: disimpan atau tidak
const isInStock = (book) => book.stock > 0;
// Hanya element yang mengembalikan true yang masuk ke array baru
const available = books.filter(isInStock);
console.log(available.length); // 2
console.log(available[0].title); // Dasar Jaringan
console.log(books.length); // 3
true yang masuk ke available. Jumlahnya berkurang sebanyak element yang dibuang, dan element yang tersisa bergeser ke depan untuk mengisi celahnya.Dari available, yang bisa kamu baca hanya posisi setelah bergeser; index tiap item di books tidak ikut tersimpan. Cara memakai posisi aslinya dibahas di bagian akhir artikel ini. Tabel di bawah merangkum bagaimana ketiga method memakai return value dari function yang kamu berikan.
| Method | Return value callback | Jumlah element array hasilnya |
|---|---|---|
| map | Masuk ke array baru | Sama dengan array asli |
| filter | Kalau true, element-nya disimpan | Sama dengan array asli atau lebih sedikit |
| forEach | Diabaikan | Tidak membuat array (return undefined) |
Kurung Kurawal Butuh return
Kalau body-nya kamu tulis di dalam kurung kurawal, seperti (book) => { book.stock > 0 }, return value-nya adalah undefined selama kamu tidak menulis return. undefined itu falsy, jadi tidak ada element yang disimpan dan hasilnya array kosong. Untuk pengecekan 1 baris, tulis tanpa kurung kurawal.
Saring Dulu, Baru Ubah — Menyambung filter dan map
Misalnya kamu ingin mengubah kursus yang sudah dipublikasikan saja menjadi string untuk ditampilkan. Kamu bisa menyimpan hasil filter ke variable lalu memanggil .map(...) pada variable itu di baris berikutnya, tapi artinya kamu memberi nama pada array perantara yang tidak akan dipakai lagi.
filter juga mengembalikan array, jadi kamu bisa langsung memanggil .map(...) pada return value-nya. Cara menyambung pemanggilan method seperti ini disebut chaining (memanggil method berikutnya pada return value method sebelumnya).
const courses = [
{ title: "Pengenalan Git", minutes: 45, published: true },
{ title: "Latihan SQL", minutes: 90, published: false },
{ title: "Dasar Linux", minutes: 60, published: true },
];
// Sisakan yang sudah dipublikasikan, lalu ubah hasilnya menjadi string untuk ditampilkan
// Tanda . di awal baris memanggil method pada hasil baris sebelumnya (tetap 1 expression)
const labels = courses
.filter((course) => course.published) // published sudah berupa boolean, jadi langsung dikembalikan
.map((course) => `${course.title} (${course.minutes} menit)`);
console.log(labels.join(" / "));
// Pengenalan Git (45 menit) / Dasar Linux (60 menit)
console.log(labels.length); // 2
console.log(courses.length); // 3
.map membaca array yang dikembalikan filter tanpa array itu pernah diberi nama. Tiap langkah dalam chain membuat 1 array baru.Kalau ingin memeriksa hasil perantaranya, simpan hasil filter ke variable, tampilkan dengan console.log, lalu panggil .map(...) pada variable itu. Setelah selesai memeriksa, kamu bisa menyatukannya kembali menjadi chain.
Mengetahui Posisi Element — index di Callback
Misalnya kamu ingin menambahkan peringkat seperti "#1" dan "#2" ke daftar ranking. Element-nya sendiri tidak menyimpan peringkat, jadi kamu mungkin tergoda menaruh variable penghitung di luar callback lalu menambahnya dengan 1 setiap kali callback dipanggil.
map dan filter memberikan element sebagai argument pertama callback, dan posisi element itu (index-nya, dihitung dari 0) sebagai argument kedua. Argument dicocokkan berdasarkan urutan, jadi walaupun kamu hanya butuh index-nya, parameter pertama tetap harus ditulis. Kalau parameter kedua itu kamu beri nama index, kamu bisa memakainya untuk menampilkan peringkat sekaligus untuk mengecek apakah sebuah element termasuk beberapa element pertama.
const ranking = ["Earbuds Wireless", "Power Bank", "Stand HP", "USB Hub"];
// Argument kedua adalah posisi yang dihitung dari 0
const lines = ranking.map((item, index) => `#${index + 1}: ${item}`);
console.log(lines.join("\n"));
// #1: Earbuds Wireless
// #2: Power Bank
// #3: Stand HP
// #4: USB Hub
// Callback filter juga menerima 2 argument yang sama
const topThree = ranking.filter((item, index) => index < 3);
console.log(topThree.length); // 3
index yang diterima filter adalah posisi di array asli. Element yang disimpan memang bergeser ke depan setelahnya, tapi itu tidak memengaruhi pengecekan, jadi index < 3 berarti 3 item pertama di array asli.
Cek Pemahaman
Jawab setiap pertanyaan satu per satu.
Soal 2Pada courses.filter(isPublished).map(toLabel), array mana yang dibaca map?
Soal 3Di callback ranking.map((item, index) => ...), apa yang diterima index?