JavaScript

Belum masuk. Progresmu tidak tersimpan.

Masuk
  • Bab 9 dari 12
  • 30 menit
  • 1 latihan kode
  • 4 soal kuis

Destructuring, Spread, dan Enhanced Object Literals

Di bab ini (7 bagian)
  1. Tujuan
  2. Destructuring: membongkar paket
  3. Default parameters
  4. Spread dan rest: titik tiga yang sama, arah berlawanan
  5. Enhanced object literals
  6. Kesalahan umum
  7. Rangkuman

Tujuan bab ini

  • Mengambil isi array dan objek ke variabel terpisah dengan destructuring, lengkap dengan default, rename, dan nested.
  • Memakai destructuring langsung di parameter fungsi dan memberi nilai default pada parameter.
  • Membedakan spread (membongkar) dan rest (mengumpulkan) meski sama-sama ditulis ....
  • Menulis objek lebih ringkas dengan shorthand property, shorthand method, dan computed property.

Destructuring: membongkar paket

Bayangkan kamu menerima paket berisi tiga barang. Cara lama: buka paket, ambil barang pertama, taruh di meja, ambil barang kedua, dan seterusnya, satu per satu. Destructuring membuatmu bisa bilang, "barang pertama ke tangan kiri, barang kedua ke tangan kanan," dalam satu baris.

Destructuring array

Untuk array, yang menentukan adalah urutan posisi.

const warna = ["merah", "hijau", "biru"];

// Cara lama
const w1 = warna[0];
const w2 = warna[1];

// Destructuring
const [utama, kedua, ketiga] = warna;
console.log(utama, ketiga); // merah biru

// Lewati elemen dengan koma kosong
const [, , terakhir] = warna;
console.log(terakhir); // biru

// Nilai default kalau elemennya tidak ada
const [a, b, c, d = "ungu"] = warna;
console.log(d); // ungu

Trik populer: menukar nilai dua variabel tanpa variabel sementara.

let x = 1;
let y = 2;
[x, y] = [y, x];
console.log(x, y); // 2 1

Destructuring objek

Untuk objek, yang menentukan adalah nama properti, bukan urutan.

const mhs = { nama: "Dini", nim: "0597", jurusan: "TI" };

const { nama, jurusan } = mhs;
console.log(nama, jurusan); // Dini TI

Rename dilakukan dengan properti: namaBaru. Bacanya: "ambil nim, simpan sebagai id".

const { nim: id } = mhs;
console.log(id); // 0597
// console.log(nim); -> ReferenceError, karena yang dibuat hanya id

Default dipakai kalau propertinya tidak ada atau bernilai undefined. Rename dan default bisa digabung.

const { umur = 20, kota: domisili = "Klaten" } = mhs;
console.log(umur, domisili); // 20 Klaten

Penting: default hanya berlaku untuk undefined. Kalau nilainya null, 0, atau "", nilai itulah yang dipakai.

Nested destructuring

Data dari API sering bertingkat. Destructuring bisa mengikuti bentuknya.

const user = {
  nama: "Rina",
  alamat: { kota: "Klaten", kodePos: "57411" },
  hobi: ["musik", "lari"],
};

const {
  alamat: { kota },
  hobi: [hobiUtama],
} = user;

console.log(kota, hobiUtama); // Klaten musik

Perhatikan bahwa alamat: di sini hanya "jalan masuk"; tidak ada variabel bernama alamat yang dibuat. Kalau user.alamat ternyata undefined, baris ini melempar TypeError, jadi beri default alamat: { kota } = {} kalau datanya tidak pasti.

Destructuring di parameter fungsi

Ini pemakaian yang paling sering kamu lihat, misalnya pada props di React. Fungsi menerima satu objek, lalu langsung dibongkar di daftar parameter.

function kartu({ nama, nim, aktif = true }) {
  return `${nama} (${nim}) ${aktif ? "aktif" : "cuti"}`;
}

console.log(kartu({ nama: "Rio", nim: "01" }));
// Rio (01) aktif
console.log(kartu({ nim: "02", nama: "Ayu", aktif: false }));
// Ayu (02) cuti

Keuntungannya: urutan argumen tidak penting lagi, dan nama properti sekaligus jadi dokumentasi.

Default parameters

Sebelum ES6, nilai bawaan parameter ditulis manual dengan ||. Masalahnya, || juga mengganti nilai "falsy" yang sah seperti 0.

// ES5
function diskonLama(harga, persen) {
  persen = persen || 10;
  return harga - (harga * persen) / 100;
}
console.log(diskonLama(1000, 0)); // 900, padahal maunya tanpa diskon!

// ES6
function diskon(harga, persen = 10) {
  return harga - (harga * persen) / 100;
}
console.log(diskon(1000));    // 900
console.log(diskon(1000, 0)); // 1000
console.log(diskon(1000, undefined)); // 900

Default parameter hanya aktif untuk argumen yang tidak diberikan atau undefined. Nilainya juga boleh berupa ekspresi dan boleh merujuk parameter sebelumnya:

function buatId(prefix = "USR", nomor = 1, id = `${prefix}-${nomor}`) {
  return id;
}
console.log(buatId());          // USR-1
console.log(buatId("ADM", 7));  // ADM-7

Spread dan rest: titik tiga yang sama, arah berlawanan

Keduanya ditulis ..., dan yang membedakan adalah posisinya.

  • Spread muncul di tempat nilai dipakai (isi array, isi objek, argumen pemanggilan). Ia membongkar kumpulan jadi elemen-elemen.
  • Rest muncul di tempat nilai ditampung (parameter fungsi, sisi kiri destructuring). Ia mengumpulkan sisa elemen jadi satu array atau objek.

Spread

const a = [1, 2, 3];
const b = [...a, 4, 5];
console.log(b); // [ 1, 2, 3, 4, 5 ]

const salinan = [...a];
salinan.push(99);
console.log(a); // [ 1, 2, 3 ]  (asli aman)

console.log(Math.max(...a)); // 3

const profil = { nama: "Sari", kota: "Solo" };
const update = { ...profil, kota: "Klaten", umur: 21 };
console.log(update); // { nama: 'Sari', kota: 'Klaten', umur: 21 }

Pada objek, properti yang ditulis belakangan menang. Itulah cara populer "mengubah" objek tanpa menyentuh aslinya. Spread objek resmi masuk di ES2018, sedangkan spread array sudah ada sejak ES6.

Satu catatan: salinan dengan spread itu dangkal (shallow). Objek di dalam objek masih menunjuk ke data yang sama.

Rest

function jumlah(...angka) {
  return angka.reduce((total, n) => total + n, 0);
}
console.log(jumlah(1, 2, 3)); // 6
console.log(jumlah());        // 0

const [pertama, ...sisanya] = [10, 20, 30, 40];
console.log(pertama, sisanya); // 10 [ 20, 30, 40 ]

const { password, ...aman } = { user: "dini", password: "rahasia", role: "admin" };
console.log(aman); // { user: 'dini', role: 'admin' }

Contoh terakhir sering dipakai untuk membuang properti sensitif sebelum data dikirim. Aturannya: rest harus paling akhir dan hanya boleh satu.

Enhanced object literals

ES6 membuat penulisan objek jauh lebih ringkas.

const nama = "Rian";
const umur = 21;
const key = "status";

// ES5
var mhsLama = {
  nama: nama,
  umur: umur,
  sapa: function () {
    return "Halo";
  },
};

// ES6
const mhs = {
  nama,            // shorthand property: sama dengan nama: nama
  umur,
  sapa() {         // shorthand method
    return `Halo, aku ${this.nama}`;
  },
  [key]: "aktif",           // computed property
  [`skor_${umur}`]: 90,     // nama properti dari ekspresi
};

console.log(mhs.sapa()); // Halo, aku Rian
console.log(mhs.status); // aktif
console.log(mhs.skor_21); // 90
  • Shorthand property: kalau nama variabel sama dengan nama properti, cukup tulis sekali.
  • Shorthand method: tulis sapa() {} tanpa : function. Method ini tetap punya this normal, jadi aman dipakai untuk method (beda dengan arrow function).
  • Computed property: ekspresi di dalam [ ] dihitung dulu, hasilnya jadi nama properti. Berguna saat nama properti baru diketahui saat program berjalan.

Kesalahan umum

  • Mengira destructuring objek ikut urutan. Objek dicocokkan berdasarkan nama, array berdasarkan posisi.
  • Bingung arah rename. { nim: id } membuat variabel id, bukan nim.
  • Membongkar objek yang undefined. const { a } = undefined langsung TypeError; beri default = {}.
  • Mengira default berlaku untuk null. Default hanya untuk undefined.
  • Mengira spread menyalin dalam. Objek bersarang tetap berbagi referensi.
  • Menaruh rest di tengah, misalnya [a, ...b, c], yang langsung SyntaxError.

Rangkuman

  • Destructuring array mengambil berdasarkan posisi, destructuring objek berdasarkan nama properti.
  • Rename memakai properti: nama, default memakai = nilai, dan pola bisa bersarang atau langsung dipakai di parameter fungsi.
  • Default parameter aktif saat argumen tidak diberikan atau undefined, lebih aman daripada ||.
  • Spread ... membongkar array atau objek; rest ... mengumpulkan sisa nilai dan harus paling akhir.
  • Enhanced object literals: shorthand property, shorthand method, dan computed property [ekspresi].

Selesaikan bab ini

  1. 1. Baca materi
  2. 2. Latihan kode (1)
  3. 3. Kuis (4 soal)

Latihan kode: Olah data profil dengan sintaks ES6

Lengkapi empat fungsi berikut:

  • ringkasUser(user) memakai destructuring (boleh langsung di parameter). Ambil nama, umur (default 17), dan alamat.kota (default "Tidak diketahui", juga kalau alamat tidak ada). Kembalikan "<nama>, <umur> tahun, <kota>". Contoh: ringkasUser({ nama: "Rina", alamat: { kota: "Klaten" } }) menghasilkan "Rina, 17 tahun, Klaten".
  • gabungProfil(lama, baru) mengembalikan objek baru gabungan keduanya (properti baru menang) tanpa mengubah lama. Pakai spread.
  • jumlahkan(...angka) menerima berapa pun angka dan mengembalikan totalnya. Tanpa argumen hasilnya 0.
  • buatField(nama, nilai) mengembalikan objek dengan satu properti bernama sesuai isi nama. Contoh: buatField("email", "a@b.c") menghasilkan { email: "a@b.c" }.

Cek pemahaman

  1. 1Setelah baris `const { nim: id } = mhs;`, variabel apa yang dibuat?

  2. 2Apa yang ditampilkan kode berikut?

    function f(a, b = 5) {
      return a + b;
    }
    console.log(f(1), f(1, null), f(1, undefined));
  3. 3Apa yang ditampilkan kode berikut?

    const [x, ...y] = [1, 2, 3, 4];
    const o = { a: 1, b: 2, ...{ b: 9, c: 3 } };
    console.log(y.length, o.b);
  4. 4Fitur apa yang dipakai pada objek `{ [kunci]: "aktif" }`?