Menu

Type Coercion JavaScript: Konversi Implisit vs Eksplisit

Bagaimana JavaScript mengonversi nilai antartipe: aturan implisit yang sering menjebak, konversi eksplisit yang sebaiknya kamu utamakan, dan kapan masing-masing terjadi.

Halaman ini dilengkapi editor yang bisa dijalankan. Edit, jalankan, dan lihat output-nya seketika.

Dua jenis coercion

JavaScript longgar soal tipe. Saat sebuah operator menerima nilai dengan tipe yang "salah", bahasanya tidak melempar error, melainkan mengonversinya. Konversi itu disebut coercion, dan ada dua jenisnya:

  • Eksplisit: kamu yang memintanya: Number("42"), String(99), Boolean(value).
  • Implisit: sebuah operator memicunya tanpa kamu menulis konversi: "5" - 2, "" == 0, if (value).

Keduanya akhirnya memakai aturan konversi dasar yang sama. Bedanya ada pada siapa yang memutuskan untuk mengonversi, kamu atau bahasanya. Hampir setiap hasil JavaScript yang membingungkan, seperti "5" + 1 === "51", [] == false, null == undefined, berasal dari coercion implisit yang tidak kamu sadari.

Cara memikirkannya: kalau kamu mengetik Number(...) atau String(...), kamu tahu apa yang kamu minta. Kalau tidak, setiap operator punya pendapatnya sendiri soal apa yang harus dilakukan, dan di pendapat-pendapat itulah bug bersarang.

Tiga tipe tujuan

Coercion selalu mengonversi ke salah satu dari tiga tipe primitif: string, number, atau boolean. (Ada yang keempat, bigint, tapi tipe lain tidak pernah otomatis dikonversi menjadi bigint.) Semua aturan lainnya mengikuti dari tipe tujuan yang dituju sebuah operator.

Konversi ke string adalah yang paling pemaaf: setiap nilai punya bentuk string. Perhatikan bahwa object diubah menjadi "[object Object]" yang tidak berguna, dan itulah kenapa mencatat object yang disambung dengan string ("user: " + user) hampir tidak pernah menampilkan yang kamu mau. Pakai JSON.stringify atau template literal dengan field tertentu.

Konversi ke number

Konversi ke number lebih ketat. String harus benar-benar terlihat seperti angka, kalau tidak kamu mendapat NaN:

Kejutan yang diberi tanda di dalam kurung adalah yang perlu dihafal:

  • String kosong dan string yang hanya berisi whitespace menjadi 0, bukan NaN.
  • null menjadi 0, tapi undefined menjadi NaN.
  • Array kosong menjadi 0; array satu elemen dikonversi menjadi elemen itu; array dengan banyak elemen menjadi NaN.

Kalau kamu ingin mengambil angka dari string yang punya karakter tambahan, pakai parseInt atau parseFloat, bukan Number:

Selalu kirim radix (10) ke parseInt. Tanpanya, string yang diawali "0x" di-parse sebagai heksadesimal, yang jarang kamu maksudkan.

Konversi ke boolean

Konversi ke boolean adalah yang paling sederhana di antara ketiganya. Ada daftar pendek nilai yang dikonversi menjadi false; selebihnya true.

Nilai falsy adalah:

  • false
  • 0, -0, 0n
  • "" (string kosong)
  • null
  • undefined
  • NaN

Itu saja. Setiap nilai lain, termasuk "false", "0", [], dan {}, bersifat truthy.

Hasil untuk array kosong dan object kosong menjebak orang yang datang dari Python, tempat koleksi kosong bersifat falsy. Di JavaScript, keduanya truthy. Kalau kamu ingin tahu "apakah array ini kosong?", cek arr.length === 0 secara eksplisit.

Konversi ke boolean terjadi setiap kali sebuah nilai muncul di tempat yang mengharapkan boolean: if (...), while (...), ternary ? :, dan operator logika &&, ||, !.

Operator + adalah kasus khusus

Sebagian besar operator aritmetika memaksa operand-nya menjadi number. + berbeda: kalau salah satu sisinya string, + melakukan penyambungan string. Kalau tidak, ia melakukan penjumlahan angka.

Evaluasinya dari kiri ke kanan. 1 + 2 + "3" pertama menghitung 1 + 2 = 3, lalu 3 + "3" = "33". Tapi "1" + 2 + 3 dimulai sebagai string dan tetap string: "12", lalu "123".

Itulah kenapa menyusun string dengan + itu rapuh. Template literal tidak punya masalah ini:

Template literal mengevaluasi count + 1 sebagai ekspresi numerik tersendiri, lalu menyisipkan hasilnya. Tanpa coercion yang mengejutkan.

Utamakan konversi eksplisit

Saat kamu perlu mengonversi tipe, tulis dengan jelas. Biayanya hanya beberapa karakter, dan semua ambiguitas hilang bagi pembaca berikutnya:

Sama halnya dengan boolean. !!value berfungsi dan umum dipakai, tapi Boolean(value) mengatakan persis apa yang dilakukannya:

Aturan yang masuk akal: pakai konversi eksplisit di logika aplikasi, dan simpan bentuk singkat (+x, !!x) untuk tempat yang mengutamakan keringkasan dan maksudnya jelas dari konteks.

Operator == sangat bergantung pada coercion

Operator kesetaraan adalah sumber kejutan coercion terbesar. == melakukan coercion sebelum membandingkan; === tidak.

Setiap true di atas adalah hasil rantai coercion bertahap yang tidak bisa dihafal oleh sebagian besar developer. Itulah masalahnya: kode yang berjalan karena kebetulan adalah kode yang akan rusak nanti. Kita akan membahas aturan kesetaraan selengkapnya di halaman berikutnya; untuk sekarang, pelajarannya: pakai === sebagai default, dan pakai == hanya untuk idiom khusus x == null (yang menangkap null sekaligus undefined).

Menyatukan semuanya

Contoh yang menunjukkan di mana coercion membantu dan di mana ia merugikan:

Perhatikan pemanggilan kedua. Number("") mengembalikan 0, bukan NaN, sehingga parsePrice("") mengembalikan 0, yang kemungkinan besar bukan yang diinginkan pemakai fungsi ini. Kalau input kosong harus ditolak, tambahkan pengecekan eksplisit:

Mengetahui nilai mana yang dikonversi menjadi 0 dan mana yang menjadi NaN adalah jenis pengetahuan yang menyelamatkanmu dari bug halus di tahap berikutnya.

Yang perlu kamu ingat

  • Coercion mengonversi ke string, number, atau boolean, tergantung operatornya.
  • + dengan string apa pun menjadi penyambungan; semua operator aritmetika lain mengonversi ke number.
  • Nilai falsy adalah daftar pendek yang tetap, jadi hafalkan. Selebihnya truthy, termasuk [] dan {}.
  • Number("") bernilai 0, Number([]) bernilai 0, Number(null) bernilai 0, tapi Number(undefined) bernilai NaN. Hal-hal ini muncul di bug sungguhan.
  • Utamakan Number(x), String(x), Boolean(x) daripada trik implisit yang cerdik. Dirimu di masa depan akan berterima kasih.

Berikutnya: operator kesetaraan

Semua yang dilakukan coercion dalam perbandingan ada di dalam ==. Halaman berikutnya membahas == vs === vs Object.is, satu-satunya idiom yang membuat == masih berguna, dan kenapa linter secara default menandai bentuk yang longgar.

Pertanyaan yang sering diajukan

Apa itu type coercion di JavaScript?

Type coercion adalah JavaScript yang otomatis mengonversi sebuah nilai dari satu tipe ke tipe lain: number menjadi string, string menjadi number, atau apa pun menjadi boolean. Ini terjadi secara implisit saat operator seperti +, ==, atau if menerima nilai yang bukan tipe yang diharapkannya, dan secara eksplisit saat kamu sendiri memanggil Number(x), String(x), atau Boolean(x).

Apa bedanya coercion implisit dan eksplisit?

Coercion eksplisit adalah saat kamu sengaja memanggil fungsi konversi: Number("42"), String(99), Boolean(value). Coercion implisit adalah saat sebuah operator memicu konversi diam-diam: "5" - 2 menghasilkan 3, "5" + 2 menghasilkan "52". Yang eksplisit mudah dibaca dan bisa diprediksi; yang implisit adalah sumber sebagian besar bug "kenapa ini NaN".

Bagaimana cara mengubah string menjadi number di JavaScript?

Pakai Number("42") untuk konversi yang ketat (mengembalikan NaN kalau string-nya bukan angka yang valid), atau parseInt("42px", 10) / parseFloat("3.14em") kalau kamu ingin membaca angka dari bagian depan string yang lebih berantakan. Operator unary + (+"42") melakukan hal yang sama dengan Number(), tapi lebih mudah terlewat saat membaca kode sekilas.

Kenapa [] + [] menghasilkan string kosong?

Operator + tidak punya operasi numerik yang bermakna untuk dua array, jadi JavaScript mengonversi keduanya menjadi string. Array diubah menjadi string dengan menggabungkan elemennya memakai koma, dan array kosong menjadi "". Jadi [] + [] menjadi "" + "", yang hasilnya "". Trik ini seru untuk dipamerkan, sekaligus alasan bagus untuk tidak pernah mengandalkan + pada nilai non-primitif.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai