Dua struktur data yang paling banyak digunakan dalam JavaScript adalah Object
dan Array
.
Objek memungkinkan kita membuat satu entitas yang menyimpan item data berdasarkan kunci.
Array memungkinkan kita mengumpulkan item data ke dalam daftar terurut.
Namun, saat kita meneruskannya ke suatu fungsi, kita mungkin tidak memerlukan semuanya. Fungsi tersebut mungkin hanya memerlukan elemen atau properti tertentu.
Penugasan destrukturisasi adalah sintaks khusus yang memungkinkan kita untuk "membongkar" array atau objek ke dalam sekumpulan variabel, karena terkadang hal itu lebih nyaman.
Destrukturisasi juga berfungsi baik dengan fungsi kompleks yang memiliki banyak parameter, nilai default, dan sebagainya. Kita akan segera melihatnya.
Berikut ini contoh bagaimana array didestrukturkan menjadi variabel:
// kita mempunyai array dengan nama dan nama keluarga biarkan arr = ["John", "Smith"] // merusak tugas // menyetel Nama Depan = arr[0] // dan nama keluarga = arr[1] biarkan [Nama Depan, Nama Belakang] = arr; peringatan(Nama Depan); // Yohanes peringatan (nama keluarga); // Smith
Sekarang kita dapat bekerja dengan variabel, bukan anggota array.
Ini tampak hebat bila dikombinasikan dengan metode split
atau pengembalian array lainnya:
biarkan [namadepan, nama keluarga] = "John Smith".split(' '); peringatan(Nama Depan); // Yohanes peringatan (nama keluarga); // Smith
Seperti yang Anda lihat, sintaksnya sederhana. Namun ada beberapa detail yang aneh. Mari kita lihat lebih banyak contoh untuk memahaminya dengan lebih baik.
“Merusak” tidak berarti “merusak”.
Ini disebut “penugasan destrukturisasi,” karena “destrukturisasi” dilakukan dengan menyalin item ke dalam variabel. Namun, susunannya sendiri tidak diubah.
Ini hanyalah cara singkat untuk menulis:
// biarkan [Nama Depan, Nama Belakang] = arr; biarkan Namadepan = arr[0]; biarkan nama keluarga = arr[1];
Abaikan elemen menggunakan koma
Elemen array yang tidak diinginkan juga dapat dibuang melalui koma tambahan:
// elemen kedua tidak diperlukan let [firstName, , title] = ["Julius", "Caesar", "Konsul", "Republik Romawi"]; peringatan( judul ); // Konsul
Dalam kode di atas, elemen kedua dari array dilewati, elemen ketiga ditetapkan ke title
, dan item array lainnya juga dilewati (karena tidak ada variabel untuk elemen tersebut).
Bekerja dengan iterable apa pun di sisi kanan
…Sebenarnya, kita bisa menggunakannya dengan iterable apa pun, tidak hanya array:
misalkan [a,b,c] = "abc"; //["a", "b", "c"] misalkan [satu, dua, tiga] = Set baru([1, 2, 3]);
Itu berhasil, karena secara internal tugas destrukturisasi bekerja dengan melakukan iterasi pada nilai yang benar. Ini semacam gula sintaksis untuk memanggil for..of
atas nilai di sebelah kanan =
dan menetapkan nilai.
Tetapkan ke apa pun di sisi kiri
Kita dapat menggunakan “assignable” apa pun di sisi kiri.
Misalnya, properti objek:
biarkan pengguna = {}; [nama.pengguna, nama belakang pengguna.] = "John Smith".split(' '); alert(nama pengguna); // Yohanes alert(pengguna.nama keluarga); // Smith
Perulangan dengan .entries()
Pada bab sebelumnya, kita melihat metode Object.entries(obj).
Kita dapat menggunakannya dengan destrukturisasi untuk mengulang kunci dan nilai suatu objek:
biarkan pengguna = { nama: "Yohanes", usia: 30 }; // mengulang kunci-dan-nilai for (biarkan [kunci, nilai] dari Objek.entri(pengguna)) { peringatan(`${kunci}:${nilai}`); // nama:John, lalu umur:30 }
Kode serupa untuk Map
lebih sederhana, karena dapat diubah:
biarkan pengguna = Peta baru(); pengguna.set("nama", "John"); pengguna.set("umur", "30"); // Peta diiterasi sebagai pasangan [kunci, nilai], sangat nyaman untuk destrukturisasi for (biarkan [kunci, nilai] pengguna) { peringatan(`${kunci}:${nilai}`); // nama:John, lalu umur:30 }
Trik menukar variabel
Ada trik terkenal untuk menukar nilai dua variabel menggunakan tugas destrukturisasi:
biarkan tamu = "Jane"; biarkan admin = "Pete"; // Ayo tukar nilainya: make guest=Pete, admin=Jane [tamu, admin] = [admin, tamu]; peringatan(`${tamu} ${admin}`); // Pete Jane (berhasil bertukar!)
Di sini kita membuat array sementara yang terdiri dari dua variabel dan segera mendestrukturkannya dalam urutan pertukaran.
Kita dapat menukar lebih dari dua variabel dengan cara ini.
Biasanya, jika array lebih panjang dari daftar di sebelah kiri, item “ekstra” akan dihilangkan.
Misalnya, di sini hanya dua item yang diambil, dan sisanya diabaikan saja:
let [nama1, nama2] = ["Julius", "Caesar", "Konsul", "Republik Romawi"]; peringatan(nama1); // Julius peringatan(nama2); // Kaisar // Item selanjutnya tidak ditugaskan ke mana pun
Jika kita juga ingin mengumpulkan semua hal berikut – kita dapat menambahkan satu parameter lagi yang mendapatkan “sisanya” menggunakan tiga titik "..."
:
let [name1, name2, ...rest] = ["Julius", "Caesar", "Konsul", "Republik Romawi"]; // sisanya adalah array item, dimulai dari item ke-3 waspada(istirahat[0]); // Konsul waspada(istirahat[1]); // Republik Romawi alert(istirahat.panjang); // 2
Nilai rest
adalah array dari elemen array yang tersisa.
Kita bisa menggunakan nama variabel lain sebagai pengganti rest
, cukup pastikan nama variabel tersebut memiliki tiga titik di depannya dan berada di urutan terakhir dalam penugasan destrukturisasi.
let [nama1, nama2, ...judul] = ["Julius", "Caesar", "Konsul", "Republik Romawi"]; // sekarang title = ["Konsul", "Republik Romawi"]
Jika array lebih pendek dari daftar variabel di sebelah kiri, tidak akan ada kesalahan. Nilai yang tidak ada dianggap tidak terdefinisi:
misalkan [Nama Depan, Nama Belakang] = []; peringatan(Nama Depan); // belum diartikan peringatan (nama keluarga); // belum diartikan
Jika kita ingin nilai “default” menggantikan nilai yang hilang, kita dapat menyediakannya menggunakan =
:
// nilai bawaan biarkan [nama = "Tamu", nama keluarga = "Anonim"] = ["Julius"]; peringatan(nama); // Julius (dari array) peringatan (nama keluarga); // Anonim (digunakan secara default)
Nilai default dapat berupa ekspresi yang lebih kompleks atau bahkan pemanggilan fungsi. Mereka dievaluasi hanya jika nilainya tidak diberikan.
Misalnya, di sini kita menggunakan fungsi prompt
untuk dua default:
// hanya menjalankan prompt untuk nama keluarga biarkan [nama = prompt('nama?'), nama keluarga = prompt('nama keluarga?')] = ["Julius"]; peringatan(nama); // Julius (dari array) peringatan (nama keluarga); // perintah apa pun yang didapat
Harap dicatat: prompt
akan berjalan hanya untuk nilai yang hilang ( surname
).
Penugasan destrukturisasi juga bekerja dengan objek.
Sintaks dasarnya adalah:
misalkan {var1, var2} = {var1:…, var2:…}
Kita harus memiliki objek yang ada di sisi kanan, yang ingin kita bagi menjadi beberapa variabel. Sisi kiri berisi “pola” seperti objek untuk properti terkait. Dalam kasus paling sederhana, itu adalah daftar nama variabel di {...}
.
Misalnya:
biarkan pilihan = { judul: "Menu", lebar: 100, tinggi: 200 }; misalkan {judul, lebar, tinggi} = opsi; peringatan(judul); // Menu peringatan(lebar); // 100 waspada(tinggi); // 200
Properti options.title
, options.width
dan options.height
ditetapkan ke variabel terkait.
Urutannya tidak penting. Ini juga berfungsi:
// mengubah urutan let {...} misalkan {tinggi, lebar, judul} = { judul: "Menu", tinggi: 200, lebar: 100 }
Pola di sisi kiri mungkin lebih kompleks dan menentukan pemetaan antara properti dan variabel.
Jika kita ingin menetapkan properti ke variabel dengan nama lain, misalnya membuat options.width
masuk ke variabel bernama w
, maka kita dapat mengatur nama variabel menggunakan titik dua:
biarkan pilihan = { judul: "Menu", lebar: 100, tinggi: 200 }; // { sourceProperty: targetVariable } misalkan {lebar: w, tinggi: h, judul} = pilihan; // lebar -> w // tinggi -> h // judul -> judul peringatan(judul); // Menu peringatan(w); // 100 peringatan(h); // 200
Tanda titik dua menunjukkan “apa : pergi ke mana”. Pada contoh di atas, properti width
menjadi w
, properti height
menjadi h
, dan title
diberikan ke nama yang sama.
Untuk properti yang mungkin hilang, kita dapat menetapkan nilai default menggunakan "="
, seperti ini:
biarkan pilihan = { judul: "Menu" }; misalkan {lebar = 100, tinggi = 200, judul} = pilihan; peringatan(judul); // Menu peringatan(lebar); // 100 waspada(tinggi); // 200
Sama seperti array atau parameter fungsi, nilai default dapat berupa ekspresi apa pun atau bahkan pemanggilan fungsi. Mereka akan dievaluasi jika nilainya tidak diberikan.
Pada kode di bawah ini, prompt
menanyakan width
, tetapi tidak untuk title
:
biarkan pilihan = { judul: "Menu" }; misalkan {lebar = prompt("lebar?"), judul = prompt("judul?")} = pilihan; peringatan(judul); // Menu peringatan(lebar); // (apa pun hasil promptnya)
Kita juga dapat menggabungkan titik dua dan persamaan:
biarkan pilihan = { judul: "Menu" }; misalkan {lebar: w = 100, tinggi: h = 200, judul} = pilihan; peringatan(judul); // Menu peringatan(w); // 100 peringatan(h); // 200
Jika kita mempunyai objek kompleks dengan banyak properti, kita hanya dapat mengekstrak yang diperlukan saja:
biarkan pilihan = { judul: "Menu", lebar: 100, tinggi: 200 }; // hanya mengekstrak judul sebagai variabel misalkan { title } = pilihan; peringatan(judul); // Menu
Bagaimana jika objek memiliki lebih banyak properti daripada variabel yang kita miliki? Bisakah kita mengambil sebagian dan kemudian menugaskan “sisanya” ke suatu tempat?
Kita bisa menggunakan pola sisanya, sama seperti yang kita lakukan dengan array. Ini tidak didukung oleh beberapa browser lama (IE, gunakan Babel untuk melakukan polyfill), tetapi berfungsi di browser modern.
Ini terlihat seperti ini:
biarkan pilihan = { judul: "Menu", tinggi: 200, lebar: 100 }; // title = properti bernama title // rest = objek dengan properti lainnya biarkan {judul, ...rest} = opsi; // sekarang title="Menu", rest={tinggi: 200, lebar: 100} alert(istirahat.tinggi); // 200 alert(istirahat.lebar); // 100
Gotcha jika tidak ada let
Dalam contoh di atas, variabel dideklarasikan langsung dalam penugasan: let {…} = {…}
. Tentu saja, kita juga bisa menggunakan variabel yang ada, tanpa let
. Tapi ada batasannya.
Ini tidak akan berhasil:
biarkan judul, lebar, tinggi; // kesalahan pada baris ini {judul, lebar, tinggi} = {judul: "Menu", lebar: 200, tinggi: 100};
Masalahnya adalah JavaScript memperlakukan {...}
dalam aliran kode utama (bukan di dalam ekspresi lain) sebagai blok kode. Blok kode tersebut dapat digunakan untuk mengelompokkan pernyataan, seperti ini:
{ // blok kode biarkan pesan = "Halo"; // ... peringatan( pesan ); }
Jadi di sini JavaScript mengasumsikan bahwa kita memiliki blok kode, itulah sebabnya terjadi kesalahan. Kami malah ingin melakukan destrukturisasi.
Untuk menunjukkan pada JavaScript bahwa itu bukan blok kode, kita dapat membungkus ekspresi dalam tanda kurung (...)
:
biarkan judul, lebar, tinggi; // oke sekarang ({judul, lebar, tinggi} = {judul: "Menu", lebar: 200, tinggi: 100}); peringatan( judul ); // Menu
Jika sebuah objek atau larik berisi objek dan larik bersarang lainnya, kita bisa menggunakan pola sisi kiri yang lebih kompleks untuk mengekstrak bagian yang lebih dalam.
Dalam kode di bawah ini, options
memiliki objek lain di properti size
dan array di properti items
. Pola di sisi kiri tugas memiliki struktur yang sama untuk mengekstrak nilai darinya:
biarkan pilihan = { ukuran: { lebar: 100, tinggi: 200 }, item: ["Kue", "Donat"], tambahan: benar }; // destrukturisasi tugas dibagi menjadi beberapa baris untuk kejelasan membiarkan { ukuran: {// masukkan ukuran di sini lebar, tinggi }, item: [item1, item2], // tetapkan item di sini title = "Menu" // tidak ada di objek (nilai default digunakan) } = pilihan; peringatan(judul); // Menu peringatan(lebar); // 100 waspada(tinggi); // 200 peringatan(item1); // Kue peringatan(item2); // Donat
Semua properti objek options
kecuali extra
yang tidak ada di bagian kiri, ditugaskan ke variabel yang sesuai:
Terakhir, kita memiliki width
, height
, item1
, item2
dan title
dari nilai default.
Perhatikan bahwa tidak ada variabel untuk size
dan items
, karena kami mengambil kontennya.
Ada kalanya suatu fungsi memiliki banyak parameter, sebagian besar bersifat opsional. Hal ini terutama berlaku untuk antarmuka pengguna. Bayangkan sebuah fungsi yang membuat menu. Mungkin memiliki lebar, tinggi, judul, daftar item, dan sebagainya.
Inilah cara yang buruk untuk menulis fungsi seperti itu:
function showMenu(judul = "Tanpa judul", lebar = 200, tinggi = 100, item = []) { // ... }
Dalam kehidupan nyata, masalahnya adalah bagaimana mengingat urutan argumen. Biasanya, IDE mencoba membantu kita, terutama jika kodenya terdokumentasi dengan baik, namun tetap saja… Masalah lainnya adalah bagaimana memanggil suatu fungsi ketika sebagian besar parameter baik-baik saja secara default.
Seperti ini?
// tidak terdefinisi dimana nilai default baik-baik saja showMenu("Menu Saya", tidak ditentukan, tidak ditentukan, ["Item1", "Item2"])
Itu jelek. Dan menjadi tidak terbaca ketika kita menangani lebih banyak parameter.
Destrukturisasi datang untuk menyelamatkan!
Kita dapat meneruskan parameter sebagai objek, dan fungsi tersebut segera mendestrukturkannya menjadi variabel:
// kita meneruskan objek ke fungsi biarkan pilihan = { judul: "Menu saya", item: ["Item1", "Item2"] }; // ...dan segera memperluasnya ke variabel function showMenu({judul = "Tanpa judul", lebar = 200, tinggi = 100, item = []}) { // judul, item – diambil dari opsi, // lebar, tinggi – default yang digunakan peringatan( `${judul} ${lebar} ${tinggi}` ); // Menu Saya 200 100 peringatan( item ); // Barang1, Barang2 } tampilkanMenu(pilihan);
Kita juga dapat menggunakan destrukturisasi yang lebih kompleks dengan objek bersarang dan pemetaan titik dua:
biarkan pilihan = { judul: "Menu saya", item: ["Item1", "Item2"] }; fungsi tampilkanMenu({ title = "Tanpa Judul", lebar: w = 100, // lebar menjadi w tinggi: h = 200, // tinggi menjadi h item: [item1, item2] // item elemen pertama menuju ke item1, kedua ke item2 }) { peringatan( `${judul} ${w} ${h}` ); // Menu Saya 100 200 peringatan( item1 ); // Barang1 peringatan( item2 ); // Barang2 } tampilkanMenu(pilihan);
Sintaks lengkapnya sama dengan tugas destrukturisasi:
fungsi({ Properti masuk: varName = defaultValue ... })
Kemudian, untuk objek parameter, akan ada variabel varName
untuk properti incomingProperty
, dengan defaultValue
secara default.
Harap perhatikan bahwa perusakan tersebut mengasumsikan bahwa showMenu()
memang memiliki argumen. Jika kita menginginkan semua nilai secara default, maka kita harus menentukan objek kosong:
tampilkanMenu({}); // oke, semua nilai adalah default tampilkanMenu(); // ini akan menghasilkan kesalahan
Kita bisa memperbaikinya dengan menjadikan {}
sebagai nilai default untuk seluruh objek parameter:
function showMenu({ judul = "Menu", lebar = 100, tinggi = 200 } = {}) { peringatan( `${judul} ${lebar} ${tinggi}` ); } tampilkanMenu(); //Menu 100 200
Pada kode di atas, seluruh objek argumen adalah {}
secara default, jadi selalu ada sesuatu yang perlu didestrukturisasi.
Penugasan destrukturisasi memungkinkan pemetaan objek atau array secara instan ke banyak variabel.
Sintaks objek lengkap:
biarkan {prop : varName = defaultValue, ...rest} = objek
Ini berarti properti prop
harus dimasukkan ke dalam variabel varName
dan, jika tidak ada properti seperti itu, maka nilai default
harus digunakan.
Properti objek yang tidak memiliki pemetaan akan disalin ke objek rest
.
Sintaks array lengkap:
biarkan [item1 = defaultValue, item2, ...rest] = array
Item pertama menuju item1
; yang kedua masuk ke item2
, dan sisanya membuat array rest
.
Ekstraksi data dari array/objek bersarang dapat dilakukan, untuk itu sisi kiri harus memiliki struktur yang sama dengan sisi kanan.
pentingnya: 5
Kami memiliki objek:
biarkan pengguna = { nama: "Yohanes", tahun: 30 };
Tulislah tugas destrukturisasi yang berbunyi:
name
properti ke dalam name
variabel.
years
properti ke dalam variabel age
.
properti isAdmin
ke dalam variabel isAdmin
(salah, jika tidak ada properti tersebut)
Berikut ini contoh nilai setelah tugas Anda:
biarkan pengguna = { nama: "John", tahun: 30 }; // kode Anda di sebelah kiri: // ... = pengguna peringatan( nama ); // Yohanes peringatan( usia ); // 30 peringatan( isAdmin ); // PALSU
biarkan pengguna = { nama: "Yohanes", tahun: 30 }; misalkan {nama, tahun: umur, isAdmin = false} = pengguna; peringatan( nama ); // Yohanes peringatan( usia ); // 30 peringatan( isAdmin ); // PALSU
pentingnya: 5
Ada objek salaries
:
misalkan gaji = { "Yohanes": 100, "Pete": 300, "Maria": 250 };
Buat fungsi topSalary(salaries)
yang mengembalikan nama orang dengan bayaran tertinggi.
Jika salaries
kosong, ia harus mengembalikan null
.
Jika ada beberapa orang dengan bayaran tertinggi, kembalikan salah satu dari mereka.
PS Gunakan Object.entries
dan destrukturisasi untuk mengulangi pasangan kunci/nilai.
Buka kotak pasir dengan tes.
fungsi topGaji(gaji) { misalkan Gaji maks = 0; biarkan maxName = null; for(const [nama, gaji] dari Objek.entri(gaji)) { if (gaji maks < gaji) { maxSalary = gaji; maxName = nama; } } kembalikan maxName; }
Buka solusi dengan pengujian di kotak pasir.