`Array` objek

Artikel ini menjelaskan tentang objek Array.

Saya akan menjelaskan penggunaan praktis array secara bertahap dengan cara yang mudah dipahami.

YouTube Video

Array objek

Objek Array pada JavaScript adalah salah satu struktur terpenting yang menjadi dasar dari berbagai pemrosesan data. Dari operasi array dasar hingga fungsi tingkat tinggi yang berguna untuk transformasi data yang efisien, ada banyak fitur yang perlu Anda ketahui.

Dasar-dasar Array

Dalam JavaScript, array adalah struktur data mendasar untuk menangani banyak nilai sekaligus. Di sini, kami memperkenalkan cara membuat array serta cara membaca dan menulis elemennya dengan contoh sederhana.

 1// Create arrays in different ways
 2const arr1 = [1, 2, 3];           // array literal
 3const arr2 = new Array(4, 5, 6);  // Array constructor
 4const arr3 = Array.of(7, 8, 9);   // Array.of
 5
 6console.log("arr1 created with literal.   :", arr1);
 7console.log("arr2 created with constructor:", arr2);
 8console.log("arr3 created with Array.of.  :", arr3);
 9// arr1 created with literal.   : [ 1, 2, 3 ]
10// arr2 created with constructor: [ 4, 5, 6 ]
11// arr3 created with Array.of.  : [ 7, 8, 9 ]
12
13// Access and modify elements
14let first = arr1[0];              // read element
15console.log("First element of arr1:", first);
16// First element of arr1: 1
17
18arr1[1] = 20;                     // modify element
19console.log("arr1 after modifying index 1:", arr1);
20// arr1 after modifying index 1: [ 1, 20, 3 ]
21
22const len = arr1.length;          // get length
23console.log("Length of arr1:", len);
24// Length of arr1: 3
  • Kode ini menunjukkan tiga cara untuk membuat array, cara membaca dan memperbarui elemen menggunakan indeks, dan cara mendapatkan panjang array dengan properti length.
  • Literal array adalah yang paling umum dan mudah dibaca, serta paling sering digunakan dalam situasi sehari-hari.

Menambahkan dan Menghapus Elemen (di Akhir atau Awal)

Array memungkinkan Anda menambah atau menghapus elemen dengan mudah di bagian akhir atau awal. Operasi-operasi ini juga berguna saat menerapkan struktur seperti stack atau queue.

 1// Push and pop (stack-like)
 2const stack = [];
 3console.log("Initial stack:", stack);
 4
 5stack.push(1);                    // push 1
 6console.log("After push(1):", stack);
 7
 8stack.push(2);                    // push 2
 9console.log("After push(2):", stack);
10
11const last = stack.pop();         // pop -> 2
12console.log("Popped value:", last);
13console.log("Stack after pop():", stack);
14
15// Unshift and shift (queue-like)
16const queue = [];
17console.log("Initial queue:", queue);
18
19queue.push('a');                  // add to end
20console.log("After push('a'):", queue);
21
22queue.unshift('start');           // add to front
23console.log("After unshift('start'):", queue);
24
25const firstItem = queue.shift();  // remove from front
26console.log("Shifted value:", firstItem);
27console.log("Queue after shift():", queue);
28
29// Initial stack: []
30// After push(1): [ 1 ]
31// After push(2): [ 1, 2 ]
32// Popped value: 2
33// Stack after pop(): [ 1 ]
34
35// Initial queue: []
36// After push('a'): [ 'a' ]
37// After unshift('start'): [ 'start', 'a' ]
38// Shifted value: start
39// Queue after shift(): [ 'a' ]
  • push dan pop beroperasi pada akhir array. Mereka sangat ideal untuk menerapkan struktur stack.
  • unshift dan shift beroperasi pada awal array. Namun, perlu diperhatikan bahwa operasi di awal array memerlukan pergeseran semua indeks elemen secara internal, sehingga operasinya cukup mahal.

Menangani Elemen di Tengah (splice dan slice)

Saat menangani elemen di tengah array, pilih antara splice dan slice tergantung apakah Anda ingin memodifikasi array asli atau tidak. Jika Anda hanya ingin mengekstrak sebagian dari array, gunakan slice; jika Anda ingin memodifikasi array itu sendiri, seperti menyisipkan atau menghapus elemen, gunakan splice.

 1// slice (non-destructive)
 2const nums = [0, 1, 2, 3, 4];
 3console.log("Original nums:", nums);
 4
 5const part = nums.slice(1, 4); // returns [1, 2, 3]
 6console.log("Result of nums.slice(1, 4):", part);
 7console.log("nums after slice (unchanged):", nums);
 8
 9// splice (destructive)
10const arr = [10, 20, 30, 40];
11console.log("\nOriginal arr:", arr);
12
13// remove 1 item at index 2, insert 25 and 27
14arr.splice(2, 1, 25, 27);
15console.log("After arr.splice(2, 1, 25, 27):", arr);
16
17// Original nums: [ 0, 1, 2, 3, 4 ]
18// Result of nums.slice(1, 4): [ 1, 2, 3 ]
19// nums after slice (unchanged): [ 0, 1, 2, 3, 4 ]
20
21// Original arr: [ 10, 20, 30, 40 ]
22// After arr.splice(2, 1, 25, 27): [ 10, 20, 25, 27, 40 ]
  • slice hanya mengekstrak elemen dan tidak memodifikasi array asli.
  • splice menambah atau menghapus elemen serta memodifikasi array itu sendiri, jadi berhati-hatilah terhadap dampaknya pada perilaku array.

Iterasi (for / for...of / forEach)

Ada beberapa cara untuk memproses array secara berurutan, dan Anda dapat memilih sesuai tujuan dan preferensi gaya penulisan kode. Berikut adalah tiga konstruksi loop yang umum.

 1const items = ['apple', 'banana', 'cherry'];
 2console.log("Items:", items);
 3
 4// classic for
 5console.log("\n--- Classic for loop ---");
 6for (let i = 0; i < items.length; i++) {
 7  console.log(`Index: ${i}, Value: ${items[i]}`);
 8}
 9
10// for...of (recommended for values)
11console.log("\n--- for...of loop ---");
12for (const item of items) {
13  console.log(`Value: ${item}`);
14}
15
16// forEach (functional style)
17console.log("\n--- forEach loop ---");
18items.forEach((item, index) => {
19  console.log(`Index: ${index}, Value: ${item}`);
20});
  • for loop adalah yang paling fleksibel, memungkinkan operasi indeks dan kontrol iterasi yang detail menggunakan break dan statement lainnya.
  • for...of menyediakan cara ringkas dalam menangani nilai elemen dan paling seimbang dalam hal keterbacaan.
  • forEach memungkinkan penulisan kode bergaya fungsional dan sangat cocok untuk operasi dengan efek samping, seperti pencatatan log atau memperbarui data setiap elemen. Namun, perhatikan bahwa Anda tidak dapat menggunakan break atau continue, dan tidak cocok untuk pemrosesan asinkron dengan await.

map / filter / reduce — Fungsi Tingkat Tinggi

map, filter, dan reduce adalah fungsi tingkat tinggi yang sering digunakan saat mentransformasikan, memfilter, atau mengagregasi array. Karena Anda dapat dengan jelas mengekspresikan proses berulang, kode Anda menjadi sederhana dan mudah dipahami.

 1const numbers = [1, 2, 3, 4, 5];
 2console.log("Original numbers:", numbers);
 3
 4// map: transform each item
 5const doubled = numbers.map(n => n * 2);
 6console.log("\nResult of map (n * 2):", doubled);
 7
 8// filter: select items
 9const evens = numbers.filter(n => n % 2 === 0);
10console.log("Result of filter (even numbers):", evens);
11
12// reduce: accumulate to single value
13const sum = numbers.reduce((acc, n) => acc + n, 0);
14console.log("Result of reduce (sum):", sum);
15
16// Original numbers: [ 1, 2, 3, 4, 5 ]
17// Result of map (n * 2): [ 2, 4, 6, 8, 10 ]
18// Result of filter (even numbers): [ 2, 4 ]
19// Result of reduce (sum): 15
  • Metode-metode ini memungkinkan Anda fokus pada apa yang ingin dilakukan dengan gaya deklaratif, meningkatkan keterbacaan dan membantu menghindari efek samping yang tidak diinginkan.

find / findIndex / some / every

Berikut adalah gambaran tentang metode pencarian dan pemeriksaan kondisi. Ini berguna untuk menemukan elemen yang memenuhi syarat tertentu atau melakukan pemeriksaan boolean pada sekumpulan data.

 1const users = [
 2  { id: 1, name: 'Alice' },
 3  { id: 2, name: 'Bob' },
 4  { id: 3, name: 'Carol' }
 5];
 6
 7console.log("Users:", users);
 8
 9// Find the first user whose name is 'Bob'
10const bob = users.find(user => user.name === 'Bob');
11console.log("\nResult of find (name === 'Bob'):", bob);
12
13// Find index of the user whose id is 3
14const indexOfId3 = users.findIndex(user => user.id === 3);
15console.log("Result of findIndex (id === 3):", indexOfId3);
16
17// Check if there exists a user with id = 2
18const hasId2 = users.some(user => user.id === 2);
19console.log("Result of some (id === 2):", hasId2);
20
21// Check if all users have a numeric id
22const allHaveNumericId = users.every(user => typeof user.id === 'number');
23console.log("Result of every (id is number):", allHaveNumericId);
24// Result of find (name === 'Bob'): { id: 2, name: 'Bob' }
25// Result of findIndex (id === 3): 2
26// Result of some (id === 2): true
27// Result of every (id is number): true
  • find mengembalikan elemen pertama yang memenuhi kondisi.
  • findIndex mengembalikan indeks dari elemen yang memenuhi kondisi.
  • some mengembalikan true jika ada setidaknya satu elemen yang memenuhi kondisi.
  • every mengembalikan true jika semua elemen memenuhi kondisi.

Semua ini sangat berguna dalam pemrosesan array, jadi gunakan sesuai kebutuhan agar kode Anda tetap ringkas dan jelas.

Fungsi Pengurutan dan Perbandingan

Array diurutkan menggunakan sort, namun secara default membandingkan elemen sebagai string, yang bisa menghasilkan hasil tak terduga saat mengurutkan angka.

 1const nums = [10, 2, 33, 4];
 2console.log("Original nums:", nums);
 3
 4// Default sort: compares elements as strings (not suitable for numbers)
 5nums.sort();
 6console.log("\nAfter default sort (string comparison):", nums);
 7
 8// Numeric ascending sort using a compare function
 9nums.sort((a, b) => a - b);
10console.log("After numeric sort (a - b):", nums);
11
12// Sort objects by a property
13const people = [{ age: 30 }, { age: 20 }, { age: 25 }];
14console.log("\nOriginal people:", people);
15
16people.sort((a, b) => a.age - b.age);
17console.log("After sorting people by age:", people);
18
19// After default sort (string comparison): [ 10, 2, 33, 4 ]
20// After numeric sort (a - b): [ 2, 4, 10, 33 ]
21// Original people: [ { age: 30 }, { age: 20 }, { age: 25 } ]
22// After sorting people by age: [ { age: 20 }, { age: 25 }, { age: 30 } ]
  • Saat mengurutkan angka atau objek, selalu tentukan fungsi perbandingan untuk mendapatkan urutan yang sesuai.
  • Dalam fungsi perbandingan, nilai kembali negatif menempatkan a di depan b, positif menempatkan b di depan a, dan 0 mempertahankan urutan tetap.

Penyalinan Array dan Imutabilitas

Saat menyalin array, penting untuk memahami perbedaan antara 'salinan referensi' dan 'salinan dangkal.'. Terutama, perhatikan bahwa jika ada objek di dalam array, salinan dangkal akan menyebabkan objek di dalamnya tetap dibagi bersama.

Salinan referensi

Ketika Anda menetapkan array ke variabel lain, array itu sendiri tidak diduplikasi; sebaliknya, 'referensi' yang menunjuk ke array yang sama disalin.

 1const a = [1, 2, 3];
 2console.log("Original a:", a);
 3
 4// Reference copy; modifying b also affects a
 5const b = a;
 6console.log("\nReference copy b = a:", b);
 7// Reference copy b = a: [ 1, 2, 3 ]
 8
 9b[0] = 100;
10console.log("After modifying b[0] = 100:");
11console.log("a:", a);  // a: [ 100, 2, 3 ] (affected)
12console.log("b:", b);  // b: [ 100, 2, 3 ]
  • Dengan salinan referensi, jika Anda memodifikasi isi array menggunakan variabel salinan, perubahan tersebut juga akan tercermin di variabel asli yang merujuk pada array yang sama.

Salinan dangkal

Menggunakan slice() atau sintaks spread menciptakan 'salinan dangkal' karena hanya nilainya yang diduplikasi; array asli dan hasil salinan diperlakukan sebagai entitas terpisah.

 1const a = [1, 2, 3];
 2console.log("Original a:", a);
 3
 4// Shallow copy (new array)
 5const b = a.slice();
 6console.log("\nShallow copy using slice():", b);
 7// Shallow copy using slice(): [ 100, 2, 3 ]
 8
 9const c = [...a];
10console.log("Shallow copy using spread [...a]:", c);
11// Shallow copy using spread [...a]: [ 100, 2, 3 ]
12
13// Modifying c or d does NOT affect a
14b[1] = 200;
15c[2] = 300;
16console.log("\nAfter modifying b[1] = 200 and c[2] = 300:");
17console.log("a:", a);   // [ 100, 2, 3 ]
18console.log("b:", b);   // [ 100, 200, 3 ]
19console.log("c:", c);   // [ 100, 2, 300 ]
  • Kode ini menunjukkan bahwa salinan dangkal dari array yang dibuat oleh slice() atau sintaks spread tidak memengaruhi array aslinya.

Salinan dangkal dan imutabilitas

Bahkan jika Anda menduplikasi array menggunakan 'salinan dangkal', pembagian yang tidak disengaja dapat terjadi jika array tersebut berisi objek di dalamnya.

 1// Shallow copy doesn't clone inner objects
 2const nested = [{ x: 1 }, { x: 2 }];
 3console.log("\nOriginal nested:", nested);
 4// Original nested: [ { x: 1 }, { x: 2 } ]
 5
 6const shallow = nested.slice();
 7console.log("Shallow copy of nested:", shallow);
 8// Shallow copy of nested: [ { x: 1 }, { x: 2 } ]
 9
10// Changing inner object affects both arrays
11shallow[0].x = 99;
12console.log("\nAfter shallow[0].x = 99:");
13console.log("nested:", nested);
14console.log("shallow:", shallow);
15// nested: [ { x: 99 }, { x: 2 } ]
16// shallow: [ { x: 99 }, { x: 2 } ]
  • Kode ini menunjukkan bahwa dengan salinan dangkal, objek di dalamnya masih dibagikan, sehingga memodifikasi objek tersebut akan memengaruhi kedua array, baik asli maupun hasil salinan.
  • Jika Anda membutuhkan data yang benar-benar mandiri, Anda memerlukan 'salinan penuh' seperti menggunakan structuredClone() atau konversi JSON.

Metode utilitas yang berguna

Berikut ini adalah metode utilitas yang sering digunakan saat bekerja dengan array. Dengan menggunakannya secara tepat sesuai tujuan, Anda bisa menulis kode yang singkat dan mudah dibaca.

includes

Metode includes memeriksa apakah suatu nilai tertentu terdapat di dalam array.

1// includes: check if array contains a value
2const letters = ['a', 'b', 'c'];
3const hasB = letters.includes('b');
4console.log("letters:", letters);  // [ 'a', 'b', 'c' ]
5console.log("letters.includes('b'):", hasB); // true
  • Pada kode ini, metode includes digunakan untuk menentukan dengan singkat apakah suatu nilai tertentu ada di dalam array.

concat

Metode concat mengembalikan array baru yang menambahkan array atau nilai yang ditentukan ke bagian akhir, sementara array aslinya tetap tidak berubah.

1// concat: merge arrays without mutation
2const a1 = [1, 2];
3const a2 = [3, 4];
4const combined = a1.concat(a2);
5console.log("a1.concat(a2):", combined); // [ 1, 2, 3, 4 ]
6console.log("a1(unchanged):", a1);       // [ 1, 2 ]
  • Kode ini menunjukkan bahwa concat bersifat non-destruktif, memungkinkan Anda membuat array baru tanpa mengubah array aslinya.

flat

Dengan menggunakan metode flat, Anda dapat meratakan array bersarang.

1// flat and flatMap: flatten arrays or map + flatten in one step
2const nested = [1, [2, [3]]];
3console.log("nested:", nested); // nested: [ 1, [ 2, [ 3 ] ] ]
4console.log("nested.flat():", nested.flat()); // default depth = 1
5// nested.flat(): [ 1, 2, [ 3 ] ]
  • Kode ini menunjukkan hasil dari meratakan sebuah array hingga satu tingkat.
  • Karena flat memungkinkan Anda menentukan kedalaman, Anda dapat mengatasi tingkat bersarang sesuai kebutuhan dengan lebih fleksibel.

flatMap

Metode flatMap menerapkan transformasi ke setiap elemen lalu secara otomatis meratakan hasilnya menjadi array satu dimensi.

1// flat and flatMap: flatten arrays or map + flatten in one step
2const words = ['hello world', 'hi'];
3console.log("words:", words); // [ 'hello world', 'hi' ]
4
5const splitWords = words.flatMap(w => w.split(' '));
6console.log("words.flatMap(w => w.split(' ')):", splitWords);
7// words.flatMap(w => w.split(' ')): [ 'hello', 'world', 'hi' ]
  • Kode ini memperlihatkan contoh di mana setiap string dalam array dipecah berdasarkan spasi, lalu hasilnya digabungkan dan diratakan menjadi satu array.

join

Metode join membuat string dengan menggabungkan elemen-elemen array menggunakan pemisah tertentu.

1// join: combine elements into a string with a separator
2const csv = ['a', 'b', 'c'].join(',');
3console.log("['a', 'b', 'c'].join(','):", csv);  // a,b,c
  • Pada kode ini, metode join digunakan untuk mengubah array menjadi string terpisah koma.

Kesalahan Umum

Operasi pada array mungkin terlihat sederhana pada pandangan pertama, tetapi ada beberapa hal yang dapat menyebabkan perilaku tak terduga. Banyak kesalahan mudah terlewatkan dalam operasi array sehari-hari, jadi mengingat hal-hal berikut akan sangat meningkatkan keandalan kode Anda.

  • sort() pada Array secara default mengurutkan berdasarkan perbandingan string. Untuk mengurutkan angka dengan benar, Anda harus selalu menyediakan fungsi perbandingan.
  • Menyalin array (menggunakan slice atau spread syntax, dll.) akan membuat salinan dangkal. Jika array Anda berisi objek, berhati-hatilah karena data asli bisa saja berubah tanpa sengaja.
  • splice adalah metode destruktif yang langsung mengubah array, sedangkan slice adalah metode tidak destruktif yang tidak memodifikasi array asli. Penting untuk menggunakannya secara tepat sesuai kebutuhan Anda.
  • forEach tidak cocok untuk loop dengan pemrosesan asinkron menggunakan await. Jika Anda ingin menjalankan pemrosesan asinkron secara berurutan dengan andal, disarankan menggunakan for...of.

Contoh Praktis

Berikut adalah contoh yang menggabungkan metode array untuk 'mengambil total umur dari data pengguna, mengekstrak mereka yang berusia 30 tahun ke atas, dan membuat daftar nama.'.

 1const users = [
 2  { name: 'Alice', age: 28 },
 3  { name: 'Bob', age: 34 },
 4  { name: 'Carol', age: 41 },
 5  { name: 'Dave', age: 19 }
 6];
 7
 8console.log("Users:", users);
 9
10// sum ages
11const totalAge = users.reduce((acc, u) => acc + u.age, 0);
12console.log("\nTotal age of all users:", totalAge);
13// Total age of all users: 122
14
15// filter and map names of users 30 and older
16const namesOver30 = users
17  .filter(u => u.age >= 30)
18  .map(u => u.name);
19
20console.log("Users aged 30 or older (names):", namesOver30);
21// Users aged 30 or older (names): [ 'Bob', 'Carol' ]
  • Dengan menggabungkan reduce, filter, dan map, Anda dapat menulis agregasi, ekstraksi kondisi, dan transformasi data dengan sederhana.
  • Pola 'data processing pipeline' seperti ini sangat mudah dibaca dan, karena minim efek samping, sering dipakai di aplikasi dunia nyata.

Ringkasan

Dengan array JavaScript, operasi dasar pun sangat luas aplikasinya, dan dengan menggunakan fungsi tingkat tinggi, kode Anda akan menjadi lebih ringkas dan ekspresif. Ada banyak poin yang perlu dipahami, tetapi begitu Anda menguasai penggunaannya secara tepat, pemrosesan data akan menjadi jauh lebih lancar.

Anda dapat mengikuti artikel di atas menggunakan Visual Studio Code di saluran YouTube kami. Silakan periksa juga saluran YouTube kami.

YouTube Video