Section ini sudah memberi kita puluhan method array: yang menambah, menghapus, mencari, mengubah, merangkum, dan mengurutkan. Dengan banyaknya pilihan, keputusan harian bergeser dari “bagaimana caranya” menjadi “yang mana yang tepat” — memilih includes atau find, mengubah array asal atau bekerja pada salinan. Keputusan yang keliru jarang menimbulkan error; akibatnya muncul jauh dari tempat kesalahannya, misalnya array konfigurasi yang tiba-tiba tersusun ulang karena disortir tanpa sengaja.

Chapter penutup ini merangkum tiga keputusan itu: memilih method sesuai tujuan, mengendalikan mutasi dengan salinan, dan mengubah nilai yang menyerupai array menjadi array sungguhan.

Memilih Method Sesuai Tujuan #

Langkah pertama sebelum menulis kode adalah menyebut hasil akhir yang diinginkan. Tabel berikut memetakan kebutuhan yang paling sering muncul ke method yang tepat:

KebutuhanMethodHasil
Mengubah bentuk tiap elemenmaparray baru, panjang sama
Menyaring berdasarkan kriteriafilterarray baru, panjang bisa berbeda
Merangkum menjadi satu nilaireducesatu nilai
Mengambil satu elemen tertentufindelemen atau undefined
Mengambil posisi berdasarkan kondisifindIndexindex atau -1
Mengecek keberadaan nilai persisincludestrue / false
Mengambil posisi nilai persisindexOfindex atau -1
Memeriksa sebagian / seluruh elemensome / everytrue / false
Mengambil potongan atau menggabungslice / concatarray baru
Menyisipkan atau menghapus di tengahsplicearray asal berubah
Mengurutkan atau membaliktoSorted / toReversedarray baru

Dua baris pertama tabel menjawab mayoritas kasus pengolahan data, dan kombinasi tiga method transformasi sudah kita rangkai di chapter map, filter, dan reduce. Baris terakhir sengaja memakai versi to* — alasannya ada di bagian berikutnya.

Method yang Mengubah vs yang Menyalin #

Semua method array terbagi dua kubu, dan garis batasnya penting. Kubu pertama bermutasi: ia mengubah array pemanggilnya — push, pop, shift, unshift, splice, sort, dan reverse. Kubu kedua menyalin: ia mengembalikan array atau nilai baru dan membiarkan asalnya utuh — slice, concat, map, filter, flat, flatMap, toSorted, toReversed, dan with.

Aturan praktisnya satu kalimat: bila array asal masih akan dipakai lagi, jangan panggil method kubu mutasi langsung atas array tersebut. Ada dua jalan keluar — salin dulu lalu mutasi salinannya, atau pakai varian salin to*:

js
const angkaAcak = [30, 10, 20];
const terurut = [...angkaAcak].sort((a, b) => a - b);
console.log(terurut);
console.log(angkaAcak);

console.log(angkaAcak.toSorted((a, b) => a - b));
console.log(angkaAcak);

Output yang Dihasilkan:

text
[ 10, 20, 30 ]
[ 30, 10, 20 ]
[ 10, 20, 30 ]
[ 30, 10, 20 ]

Tanda [...angkaAcak] membuat array baru yang berisi salinan seluruh elemen; sort kemudian bermutasi pada salinan itu, dan angkaAcak tetap [ 30, 10, 20 ]. Varian toSorted mencapai hasil yang sama dengan satu panggilan. Dua jalan ini setara hasilnya; pilih satu dan konsisten. Yang harus dihindari adalah memanggil sort atau reverse langsung pada array yang masih dipakai bagian program lain.

Salinan Dangkal: Batas yang Perlu Diketahui #

Baik slice(), [...array], maupun toSorted() semuanya membuat salinan dangkal (shallow copy) — hanya lapis terluar yang disalin. Untuk array berisi nilai primitif, ini tidak masalah. Untuk array berisi object, salinan dangkal menyalin referensinya saja, sehingga object di dalam tetap dibagi antara array asal dan salinannya:

js
const asli = [{ stok: 5 }];
const salinan = asli.slice();
salinan[0].stok = 0;
console.log(salinan[0].stok);
console.log(asli[0].stok);

Output yang Dihasilkan:

text
0
0

Yang diubah hanyalah salinan[0], tetapi asli[0].stok ikut berubah menjadi 0 — kedua array memegang referensi object yang sama. Kesadaran akan batas ini mencegah bug halus saat menyalin daftar produk atau daftar pengguna. Cara menyalin object itu sendiri, beserta pengertian referensi secara menyeluruh, adalah inti section Objects.

Callback yang Tenang: Tanpa Efek Samping #

Callback pada map, filter, find, dan kawan-kawannya paling aman bila murni: menerima elemen, mengembalikan nilai, tanpa mengubah apa pun di luar dirinya. Callback yang sambil mengubah variabel lain atau array asal membuat alur data sulit dilacak — akibatnya biasanya muncul jauh dari tempat mutasinya, saat data ternyata sudah berbentuk lain.

Bila transformasi memang membutuhkan efek samping — mencetak, menulis ke luar, atau mengubah data lain — tulis langkahnya eksplisit: simpan hasil map atau filter ke konstanta, lalu proses dengan loop for...of di baris terpisah. Niat program terbaca jauh lebih jelas daripada disembunyikan di dalam callback.

Menamai Array dan Salinannya #

Kebiasaan penamaan yang konsisten menolong saat array dan salinannya hidup berdampingan: keranjang untuk asal, salinanKeranjang untuk hasilnya; angkaAcak dan terurut di contoh babak ini mengikuti pola yang sama. Nama yang menyebut statusnya — acak, terurut, salinan — membuat pembaca tidak perlu membuka isi variabel untuk tahu apa yang dipegangnya.

Mengubah Iterable Menjadi Array #

Terkadang yang kita pegang bukan array sungguhan, melainkan iterable — struktur yang bisa ditelusuri for...of tetapi tidak memiliki method array. String adalah contohnya: ia bisa diloop per karakter, tetapi tidak punya map atau filter. Array.from mengubah iterable menjadi array; operator spread ... mencapai hal yang sama:

js
const hurufNama = Array.from("Siti");
console.log(hurufNama);

const hurufLain = [..."Budi"];
console.log(hurufLain);

Output yang Dihasilkan:

text
[ 'S', 'i', 't', 'i' ]
[ 'B', 'u', 'd', 'i' ]

Kini kedua string menjadi array huruf dengan seluruh method array siap dipakai. Array.from punya satu kemampuan tambahan: argumen kedua berupa callback yang sekaligus memetakan setiap elemen — mirip map yang menyatu. Callback-nya menerima elemen dan index; parameter pertama boleh dinamai _ ketika elemennya memang tidak dipakai, semacam konvensi penamaan untuk “diabaikan”:

js
const nomorKursi = Array.from({ length: 3 }, (_, i) => `Kursi-${i + 1}`);
console.log(nomorKursi);

Output yang Dihasilkan:

text
[ 'Kursi-1', 'Kursi-2', 'Kursi-3' ]

Argumen pertamanya, { length: 3 }, adalah object literal ringan yang hanya membawa properti length — cukup bagi Array.from untuk tahu berapa elemen yang perlu dibentuk. Pola ini praktis untuk membuat deret bernomor tanpa menulis loop. Konversi semacam ini juga menjadi jembatan ketika kita nanti menerima hasil DOM — seperti kumpulan elemen dari querySelectorAll di section DOM — yang berupa iterable, bukan array.

Contoh Lengkap: Keputusan dalam Satu Berkas #

// array-best-practices.js
// Memilih method yang tepat, menyalin sebelum mutasi, mengubah iterable jadi array.

// --- 1. Pilih method sesuai tujuan ---
const stokBuah = ["Apel", "Jeruk", "Mangga", "Jeruk"];
console.log(stokBuah.includes("Jeruk"));  // cukup tahu ada atau tidak
console.log(stokBuah.indexOf("Jeruk"));   // butuh posisi pertamanya

const semuaPendek = stokBuah.every((buah) => buah.length <= 6);
console.log(semuaPendek);

// --- 2. Salin dulu, baru mutasi: asal tetap utuh ---
const keranjang = ["Buku", "Pulpen"];
const salinanKeranjang = keranjang.slice(); // salinan dangkal (shallow copy)
salinanKeranjang.push("Penghapus");
console.log(salinanKeranjang);
console.log(keranjang);

// Mengurutkan lewat salinan, bukan array asal
const angkaAcak = [30, 10, 20];
const terurut = [...angkaAcak].sort((a, b) => a - b);
console.log(terurut);
console.log(angkaAcak);

// ES2023 menyediakan jalan pintas yang sama: toSorted
console.log(angkaAcak.toSorted((a, b) => a - b));
console.log(angkaAcak);

// --- 3. Mengubah iterable menjadi array ---
const hurufNama = Array.from("Siti");
console.log(hurufNama);

const hurufLain = [..."Budi"];
console.log(hurufLain);

// Argumen kedua Array.from sekaligus memetakan isinya
const nomorKursi = Array.from({ length: 3 }, (_, i) => `Kursi-${i + 1}`);
console.log(nomorKursi);

Output yang Dihasilkan:

text
true
1
true
[ 'Buku', 'Pulpen', 'Penghapus' ]
[ 'Buku', 'Pulpen' ]
[ 10, 20, 30 ]
[ 30, 10, 20 ]
[ 10, 20, 30 ]
[ 30, 10, 20 ]
[ 'S', 'i', 't', 'i' ]
[ 'B', 'u', 'd', 'i' ]
[ 'Kursi-1', 'Kursi-2', 'Kursi-3' ]

Mari kita telaah baris-baris pentingnya:

  1. Baris 5–6 (includes lalu indexOf): pertanyaan “adakah Jeruk?” dijawab true tanpa posisi; pertanyaan “di mana?” dijawab index 1. Dua method, dua bentuk jawaban — pilih sesuai yang dibutuhkan.
  2. Baris 9 (stokBuah.every((buah) => buah.length <= 6)): pemeriksaan kondisi atas seluruh array; semua nama berpanjang enam huruf atau kurang, sehingga hasilnya true.
  3. Baris 14–17 (slice() lalu push pada salinan): push menambah "Penghapus" hanya pada salinanKeranjang; baris berikutnya menunjukkan keranjang tetap dua elemen.
  4. Baris 22–24 ([...angkaAcak].sort(...)): salinan spread diurutkan, asal tetap [ 30, 10, 20 ] — pola aman ketika varian to* tidak tersedia.
  5. Baris 27–28 (toSorted lalu console.log(angkaAcak)): jalan pintas ES2023 menghasilkan urutan yang sama, dan array asal tetap utuh.
  6. Baris 31–34 (Array.from("Siti") dan [..."Budi"]): dua cara konversi iterable menghasilkan array huruf yang setara.
  7. Baris 38 (Array.from({ length: 3 }, (_, i) => \Kursi-${i + 1}`): pembentukan tiga elemen sekaligus pemetaannya; parameter _ menandai elemen yang diabaikan, sedangkan i memberi nomor urut.

Section Arrays tuntas di sini. Sepanjang section ini kita sudah memakai object literal untuk data produk dan membaca propertinya lewat titik — kebiasaan yang akan terasa lebih mantap setelah section Objects membongkar object secara menyeluruh: properti, method, dan cara object bekerja di balik layar.

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

array-best-practices.js

Unduh berkas
javascript
// array-best-practices.js
// Memilih method yang tepat, menyalin sebelum mutasi, mengubah iterable jadi array.

// --- 1. Pilih method sesuai tujuan ---
const stokBuah = ["Apel", "Jeruk", "Mangga", "Jeruk"];
console.log(stokBuah.includes("Jeruk"));  // cukup tahu ada atau tidak
console.log(stokBuah.indexOf("Jeruk"));   // butuh posisi pertamanya

const semuaPendek = stokBuah.every((buah) => buah.length <= 6);
console.log(semuaPendek);

// --- 2. Salin dulu, baru mutasi: asal tetap utuh ---
const keranjang = ["Buku", "Pulpen"];
const salinanKeranjang = keranjang.slice(); // salinan dangkal (shallow copy)
salinanKeranjang.push("Penghapus");
console.log(salinanKeranjang);
console.log(keranjang);

// Mengurutkan lewat salinan, bukan array asal
const angkaAcak = [30, 10, 20];
const terurut = [...angkaAcak].sort((a, b) => a - b);
console.log(terurut);
console.log(angkaAcak);

// ES2023 menyediakan jalan pintas yang sama: toSorted
console.log(angkaAcak.toSorted((a, b) => a - b));
console.log(angkaAcak);

// --- 3. Mengubah iterable menjadi array ---
const hurufNama = Array.from("Siti");
console.log(hurufNama);

const hurufLain = [..."Budi"];
console.log(hurufLain);

// Argumen kedua Array.from sekaligus memetakan isinya
const nomorKursi = Array.from({ length: 3 }, (_, i) => `Kursi-${i + 1}`);
console.log(nomorKursi);