Tetapi kenyataannya, kebenaran yang tidak menyenangkan, adalah bahwa desain kompak ini seringkali sangat berguna. Dan mereka, pada saat yang sama, cukup sederhana. Ini berarti bahwa siapa pun yang tertarik dengan kode yang digunakan dapat menguasainya dan memahami kode tersebut.
Dalam posting ini, saya akan melihat beberapa konstruksi kompak yang sangat berguna (dan terkadang samar) yang mungkin Anda temukan di JavaScript dan TypeScript. Setelah mempelajarinya, Anda dapat menggunakannya sendiri, atau setidaknya Anda dapat memahami kode programer yang menggunakannya.
1. Operator ??
Operator untuk memeriksa nilai
nulldan undefined(operator penggabungan nullish) terlihat seperti dua tanda tanya ( ??). Sulit dipercaya bahwa ini, dengan nama ini dan itu, adalah operator paling populer. Benar?
Arti dari operator ini adalah ia mengembalikan nilai operan kanan jika nilai kiri sama dengan
nullatau undefined. Ini tidak cukup jelas tercermin dalam namanya, tapi oh baiklah, apa itu - itu. Berikut cara menggunakannya:
function myFn(variable1, variable2) {
let var2 = variable2 ?? "default value"
return variable1 + var2
}
myFn("this has ", "no default value") // "this has no default value"
myFn("this has no ") // "this has no default value"
myFn("this has no ", 0) // "this has no 0"
Mekanisme yang terlibat di sini sangat mirip dengan yang digunakan untuk mengatur pekerjaan operator
||. Jika sisi kiri ekspresi sama dengan nullatau undefined, maka sisi kanan ekspresi akan dikembalikan. Jika tidak, sisi kiri akan dikembalikan. Akibatnya, operator sangat ??cocok untuk digunakan dalam situasi di mana apa pun dapat ditetapkan ke variabel, tetapi Anda perlu mengambil beberapa ukuran jika itu nullatau termasuk dalam variabel ini undefined.
2. Operator ?? =
Operator yang digunakan untuk menetapkan nilai ke variabel hanya jika memiliki nilai
nullatau undefined(operator penugasan nullish logis) terlihat seperti dua tanda tanya diikuti dengan tanda sama dengan ( ??=). Anggap saja sebagai perpanjangan dari operator di atas ??.
Mari kita lihat cuplikan kode sebelumnya, yang ditulis ulang menggunakan
??=.
function myFn(variable1, variable2) {
variable2 ??= "default value"
return variable1 + variable2
}
myFn("this has ", "no default value") // "this has no default value"
myFn("this has no ") // "this has no default value"
myFn("this has no ", 0) // "this has no 0"
Operator
??=memungkinkan Anda untuk memeriksa nilai parameter fungsi variable2. Jika sama dengan nullatau undefined, itu akan menulis nilai baru padanya. Jika tidak, nilai parameter tidak akan berubah.
Ingatlah bahwa desainnya
??=mungkin tampak tidak dapat dipahami oleh mereka yang tidak terbiasa dengannya. Oleh karena itu, jika Anda menggunakannya, Anda mungkin ingin menambahkan komentar singkat dengan penjelasan di tempat yang sesuai dalam kode.
3. Deklarasi singkat dari konstruktor TypeScript
Fitur ini khusus untuk TypeScript. Oleh karena itu, jika Anda seorang juara kemurnian JavaScript, maka Anda kehilangan banyak hal. (Hanya bercanda, tentu saja, tapi ini tidak berlaku untuk JS biasa).
Seperti yang Anda ketahui, saat mendeklarasikan kelas, mereka biasanya mencantumkan semua propertinya dengan pengubah akses, lalu, di konstruktor kelas, menetapkan nilai ke properti ini. Tetapi dalam kasus di mana konstruktor sangat sederhana, dan di dalamnya nilai parameter yang diteruskan ke konstruktor hanya dituliskan ke properti, Anda dapat menggunakan konstruksi yang lebih kompak daripada yang biasa.
Beginilah tampilannya:
// ...
class Person {
private first_name: string;
private last_name: string;
private age: number;
private is_married: boolean;
constructor(fname:string, lname:string, age:number, married:boolean) {
this.first_name = fname;
this.last_name = lname;
this.age = age;
this.is_married = married;
}
}
// , ...
class Person {
constructor( private first_name: string,
private last_name: string,
private age: number,
private is_married: boolean){}
}
Menggunakan pendekatan di atas saat membuat konstruktor pasti membantu menghemat waktu. Apalagi jika menyangkut kelas yang memiliki banyak properti.
Hal utama di sini adalah jangan lupa menambahkan
{}segera setelah deskripsi konstruktor, karena ini adalah representasi dari badan fungsi. Setelah kompilator menemukan deskripsi seperti itu, ia akan memahami segalanya dan akan melakukan sisanya sendiri. Faktanya, kita berbicara tentang fakta bahwa fragmen pertama dan kedua dari kode TS pada akhirnya akan diubah menjadi kode JavaScript yang sama.
4. Operator terner
Operator terner adalah konstruksi yang mudah dibaca. Operator ini sering digunakan sebagai pengganti instruksi singkat
if…else, karena memungkinkan Anda membuang karakter tambahan dan mengubah konstruksi multi-baris menjadi konstruksi satu baris.
// if…else
let isEven = ""
if(variable % 2 == 0) {
isEven = "yes"
} else {
isEven = "no"
}
//
let isEven = (variable % 2 == 0) ? "yes" : "no"
Dalam struktur operator terner, yang pertama adalah ekspresi logis, yang kedua adalah seperti perintah
returnyang mengembalikan nilai jika ekspresi logis benar, dan yang ketiga juga seperti perintah returnyang mengembalikan nilai jika ekspresi logis salah. Meskipun operator terner paling baik digunakan di sisi kanan penugasan nilai (seperti dalam contoh), ini juga dapat digunakan secara mandiri, sebagai mekanisme untuk memanggil fungsi ketika fungsi mana yang akan dipanggil, atau dengan argumen mana yang satu dan yang sama akan dipanggil. fungsi yang sama ditentukan oleh nilai ekspresi logis. Beginilah tampilannya:
let variable = true;
(variable) ? console.log("It's TRUE") : console.log("It's FALSE")
Perhatikan bahwa struktur pernyataan terlihat sama seperti pada contoh sebelumnya. Kerugian menggunakan operator terner adalah jika di masa mendatang Anda perlu memperluas salah satu bagiannya (baik bagian yang merujuk ke nilai sebenarnya dari ekspresi logis, atau bagian yang merujuk ke nilai salahnya), ini berarti Anda harus beralih ke instruksi normal
if…else.
5. Menggunakan siklus kalkulasi pendek yang digunakan oleh operator ||
Dalam JavaScript (dan dalam TypeScript juga), operator OR logika (
||) mengimplementasikan model komputasi singkatan. Artinya, ini mengembalikan ekspresi pertama yang dievaluasi sebagai true, dan tidak memeriksa ekspresi yang tersisa.
Artinya jika terdapat statement berikut
if, dimana ekspresi tersebut expression1mengandung nilai false (reducible to false), dan expression2- true (reducible to true), maka hanya expression1dan akan dihitung expression2. Ekspresi espression3dan expression4tidak akan dievaluasi.
if( expression1 || expression2 || expression3 || expression4)
Kami dapat memanfaatkan peluang ini di luar pernyataan
if, di mana kami menetapkan nilai ke variabel. Ini akan memungkinkan, khususnya, untuk menulis nilai default ke variabel jika beberapa nilai, katakanlah, diwakili oleh parameter fungsi, ternyata salah (misalnya, sama undefined):
function myFn(variable1, variable2) {
let var2 = variable2 || "default value"
return variable1 + var2
}
myFn("this has ", " no default value") // "this has no default value"
myFn("this has no ") // "this has no default value"
Contoh ini menunjukkan bagaimana Anda dapat menggunakan operator
||untuk menulis ke variabel baik nilai parameter kedua dari suatu fungsi atau nilai default. Namun, jika Anda mencermati contoh ini, Anda dapat melihat masalah kecil di dalamnya. Faktanya adalah jika ada variable2nilai dalam 0atau string kosong, maka nilai var2default akan ditulis, karena dan 0dan string kosong diubah menjadi false.
Oleh karena itu, jika dalam kasus Anda, Anda tidak perlu mengganti semua nilai salah dengan nilai default, Anda dapat menggunakan operator yang kurang dikenal
??.
6. Operator bitwise ganda ~
Pengembang JavaScript biasanya tidak terlalu tertarik menggunakan operator bitwise. Siapa yang peduli dengan representasi biner dari angka-angka hari ini? Tetapi faktanya adalah karena operator ini bekerja pada tingkat bit, mereka melakukan tindakan terkait jauh lebih cepat daripada, misalnya, beberapa metode.
Jika kita berbicara tentang operator bitwise NOT (
~), maka dibutuhkan sebuah angka, mengubahnya menjadi integer 32-bit (membuang bit "ekstra") dan membalik bit dari angka ini. Ini menyebabkan nilai xdiubah menjadi nilai -(x+1). Mengapa kita tertarik dengan konversi angka seperti itu? Dan fakta bahwa jika Anda menggunakannya dua kali, itu akan memberi kita hasil yang sama sebagai pemanggilan metode Math.floor.
let x = 3.8
let y = ~x // x -(3 + 1), ,
let z = ~y // y ( -4) -(-4 + 1) - 3
// :
let flooredX = ~~x //
Perhatikan dua ikon
~di baris terakhir contoh. Ini mungkin terlihat aneh, tetapi jika Anda harus mengubah banyak bilangan floating point menjadi bilangan bulat, teknik ini bisa sangat berguna.
7. Menetapkan nilai ke properti objek
Kemampuan standar ES6 menyederhanakan proses pembuatan objek dan, khususnya, proses penetapan nilai ke propertinya. Jika nilai properti ditetapkan berdasarkan variabel yang memiliki nama yang sama dengan properti ini, maka tidak perlu mengulang nama tersebut. Sebelumnya, itu perlu.
Berikut adalah contoh yang ditulis dalam TypeScript.
let name:string = "Fernando";
let age:number = 36;
let id:number = 1;
type User = {
name: string,
age: number,
id: number
}
//
let myUser: User = {
name: name,
age: age,
id: id
}
//
let myNewUser: User = {
name,
age,
id
}
Seperti yang Anda lihat, pendekatan baru untuk menetapkan nilai ke properti objek memungkinkan Anda menulis kode yang lebih ringkas dan sederhana. Pada saat yang sama, kode seperti itu tidak lebih sulit untuk dibaca daripada kode yang ditulis menurut aturan lama (yang tidak dapat dikatakan tentang kode yang ditulis menggunakan konstruksi kompak lainnya yang dijelaskan dalam artikel ini).
8. Pengembalian implisit nilai dari fungsi panah
Tahukah Anda bahwa fungsi panah garis tunggal mengembalikan hasil perhitungan yang dilakukan pada satu barisnya?
Menggunakan mekanisme ini memungkinkan Anda menyingkirkan ekspresi yang tidak perlu
return. Teknik ini sering digunakan dalam fungsi panah yang diteruskan ke metode array seperti filteratau map. Berikut adalah contoh TypeScript:
let myArr:number[] = [1,2,3,4,5,6,7,8,9,10]
// :
let oddNumbers:number[] = myArr.filter( (n:number) => {
return n % 2 == 0
})
let double:number[] = myArr.map( (n:number) => {
return n * 2;
})
// :
let oddNumbers2:number[] = myArr.filter( (n:number) => n % 2 == 0 )
let double2:number[] = myArr.map( (n:number) => n * 2 )
Menerapkan teknik ini tidak selalu berarti membuat kode menjadi lebih kompleks. Konstruksi seperti ini adalah cara yang baik untuk sedikit membersihkan kode Anda dan menghilangkan spasi dan baris ekstra yang tidak perlu. Tentu saja, kerugian dari pendekatan ini adalah jika badan dengan fungsi yang pendek perlu diperpanjang, Anda harus kembali menggunakan kurung kurawal.
Satu-satunya kekhasan yang harus diperhitungkan di sini adalah bahwa apa yang terkandung dalam satu-satunya baris dari fungsi panah pendek yang dipertimbangkan di sini harus berupa ekspresi (yaitu, harus menghasilkan beberapa hasil yang dapat dikembalikan dari fungsi). Jika tidak, desain seperti itu tidak akan berfungsi. Misalnya, fungsi satu baris di atas tidak dapat ditulis seperti ini:
const m = _ => if(2) console.log("true") else console.log("false")
Di bagian selanjutnya, kita akan terus berbicara tentang fungsi panah garis tunggal, tetapi sekarang kita akan berbicara tentang fungsi yang tidak dapat dibuat tanpa tanda kurung kurawal.
9. Parameter fungsi, yang dapat memiliki nilai default
ES6 memperkenalkan kemampuan untuk menentukan nilai yang ditetapkan ke parameter fungsi default. Sebelumnya, JavaScript tidak memiliki kemampuan seperti itu. Oleh karena itu, dalam situasi di mana perlu untuk menetapkan nilai yang serupa ke parameter, perlu menggunakan sesuatu seperti model perhitungan operator yang dikurangi
||.
Tetapi sekarang masalah yang sama dapat diselesaikan dengan sangat sederhana:
// 2
// ,
function myFunc(a, b, c = 2, d = "") {
// ...
}
Mekanismenya sederhana, bukan? Namun, pada kenyataannya, semuanya bahkan lebih menarik daripada yang terlihat pada pandangan pertama. Intinya adalah bahwa nilai default bisa apa saja - termasuk pemanggilan fungsi. Fungsi ini akan dipanggil jika parameter terkait tidak diteruskan ke sana saat fungsi dipanggil. Ini memudahkan penerapan pola parameter fungsi yang diperlukan:
const mandatory = _ => {
throw new Error("This parameter is mandatory, don't ignore it!")
}
function myFunc(a, b, c = 2, d = mandatory()) {
// ...
}
// !
myFunc(1,2,3,4)
//
myFunc(1,2,3)
Faktanya, di sini adalah fungsi panah satu baris yang tidak dapat Anda lakukan tanpa tanda kurung kurawal saat membuatnya. Intinya adalah bahwa fungsi tersebut
mandatorymenggunakan instruksi throw. Perhatikan - "instruksi", bukan "ekspresi". Tapi, saya kira, ini bukan harga tertinggi untuk kemampuan melengkapi fungsi dengan parameter yang diperlukan.
10. Mentransmisikan nilai apa pun ke tipe boolean menggunakan !!
Mekanisme ini bekerja dengan prinsip yang sama dengan konstruksi di atas
~~. Yaitu, kita berbicara tentang fakta bahwa untuk mentransmisikan nilai apa pun ke tipe logis, Anda dapat menggunakan dua operator logika BUKAN ( !!):
!!23 // TRUE
!!"" // FALSE
!!0 // FALSE
!!{} // TRUE
Satu operator
!sudah menyelesaikan sebagian besar tugas ini, yaitu mengonversi nilai menjadi tipe boolean dan kemudian mengembalikan nilai yang berlawanan. Dan operator kedua !mengambil apa yang terjadi dan hanya mengembalikan kebalikannya. Hasilnya, kami mendapatkan nilai asli dikonversi ke tipe boolean.
Konstruksi singkat ini dapat berguna dalam berbagai situasi. Pertama, ketika Anda perlu memastikan bahwa variabel diberi nilai boolean nyata (misalnya, jika kita berbicara tentang tipe variabel TypeScript
boolean). Kedua, ketika Anda perlu melakukan perbandingan yang ketat (menggunakan ===) sesuatu dengan trueatau false.
11. Merusak dan menyebarkan sintaks
Mekanisme yang disebutkan dalam judul bagian ini dapat dibicarakan dan dibicarakan. Intinya adalah, jika digunakan dengan benar, dapat memberikan hasil yang sangat menarik. Tapi di sini saya tidak akan terlalu dalam. Saya akan memberi tahu Anda cara menggunakannya untuk menyederhanakan solusi dari beberapa masalah.
▍Mendestrukturisasi objek
Pernahkah Anda menghadapi tugas menulis beberapa nilai properti objek ke dalam variabel biasa? Tugas ini cukup umum. Misalnya, ketika perlu bekerja dengan nilai-nilai ini (dengan memodifikasinya, misalnya) dan pada saat yang sama tidak mempengaruhi apa yang disimpan di objek asli.
Penggunaan penghancuran objek memungkinkan Anda untuk memecahkan masalah serupa menggunakan jumlah kode minimum:
const myObj = {
name: "Fernando",
age: 37,
country: "Spain"
}
// :
const name = myObj.name;
const age = myObj.age;
const country = myObj.country;
//
const {name, age, country} = myObj;
Siapa pun yang telah menggunakan TypeScript telah melihat sintaks ini dalam petunjuknya
import. Ini memungkinkan Anda untuk mengimpor metode pustaka individu tanpa mencemari namespace proyek dengan banyak fungsi yang tidak perlu:
import { get } from 'lodash'
Misalnya, instruksi ini memungkinkan Anda untuk mengimpor
lodashhanya metode dari perpustakaan get. Pada saat yang sama, metode lain dari pustaka ini tidak termasuk dalam namespace proyek. Dan ada banyak dari mereka di dalamnya.
▍Sebarkan sintaks dan buat objek dan larik baru berdasarkan yang sudah ada
Menggunakan sintaks spread (
…) menyederhanakan tugas untuk membuat array dan objek baru berdasarkan yang sudah ada. Sekarang tugas ini dapat diselesaikan dengan menulis satu baris kode secara harfiah dan tanpa menggunakan metode khusus apa pun. Berikut contohnya:
const arr1 = [1,2,3,4]
const arr2 = [5,6,7]
const finalArr = [...arr1, ...arr2] // [1,2,3,4,5,6,7]
const partialObj1 = {
name: "fernando"
}
const partialObj2 = {
age:37
}
const fullObj = { ...partialObj1, ...partialObj2 } // {name: "fernando", age: 37}
Perhatikan bahwa menggunakan pendekatan ini untuk menggabungkan objek akan menimpa propertinya dengan nama yang sama. Ini tidak berlaku untuk array. Secara khusus, jika array yang akan digabungkan memiliki nilai yang sama, semuanya akan berakhir di array yang dihasilkan. Jika Anda perlu menghilangkan pengulangan, maka Anda dapat menggunakan struktur data
Set.
▍Menggabungkan sintaks perusak dan menyebarkan
Destrukturisasi dapat digunakan sehubungan dengan sintaks penyebaran. Ini menghasilkan efek yang menarik. Misalnya, hapus elemen pertama dari array, dan biarkan sisanya tidak tersentuh (seperti pada contoh umum dengan elemen pertama dan terakhir dari daftar, yang implementasinya dapat ditemukan dalam Python dan bahasa lain). Dan juga, misalnya, Anda bahkan dapat mengekstrak beberapa properti dari suatu objek, dan membiarkan sisanya tidak tersentuh. Mari pertimbangkan sebuah contoh:
const myList = [1,2,3,4,5,6,7]
const myObj = {
name: "Fernando",
age: 37,
country: "Spain",
gender: "M"
}
const [head, ...tail] = myList
const {name, age, ...others} = myObj
console.log(head) //1
console.log(tail) //[2,3,4,5,6,7]
console.log(name) //Fernando
console.log(age) //37
console.log(others) //{country: "Spain", gender: "M"}
Perhatikan bahwa tiga titik yang digunakan di sisi kiri pernyataan tugas harus berlaku untuk item terakhir. Anda tidak dapat menggunakan sintaks penyebaran terlebih dahulu, lalu mendeskripsikan variabel individual:
const [...values, lastItem] = [1,2,3,4]
Kode ini tidak akan berfungsi.
Hasil
Masih banyak lagi desain yang mirip dengan yang kita bicarakan hari ini. Namun, dengan menggunakannya, perlu diingat bahwa semakin ringkas kodenya, semakin sulit untuk membacanya bagi seseorang yang tidak terbiasa dengan konstruksi singkat yang digunakan di dalamnya. Dan tujuan menggunakan konstruksi semacam itu bukanlah untuk memperkecil kode atau mempercepatnya. Tujuan ini hanya untuk menghapus struktur yang tidak perlu dari kode dan membuat hidup lebih mudah bagi orang yang akan membaca kode ini.
Oleh karena itu, untuk membuat semua orang senang, Anda disarankan untuk menjaga keseimbangan yang sehat antara konstruksi kompak dan kode yang dapat dibaca secara teratur. Perlu selalu diingat bahwa Anda bukanlah satu-satunya orang yang membaca kode Anda.
Konstruksi ringkas apa yang Anda gunakan dalam JavaScript dan kode TypeScript?
