Panduan Penting Untuk Jenis Data Terbaru JavaScript: BigInt

Diterbitkan: 2022-03-10
Ringkasan cepat Dalam JavaScript, tipe Number tidak dapat dengan aman mewakili nilai integer yang lebih besar dari 2 53 . Keterbatasan ini telah memaksa pengembang untuk menggunakan solusi yang tidak efisien dan perpustakaan pihak ketiga. BigInt adalah tipe data baru yang dimaksudkan untuk memperbaikinya.

Tipe data BigInt bertujuan untuk memungkinkan pemrogram JavaScript untuk mewakili nilai integer yang lebih besar dari rentang yang didukung oleh tipe data Number . Kemampuan untuk mewakili bilangan bulat dengan presisi arbitrer sangat penting ketika melakukan operasi matematika pada bilangan bulat besar. Dengan BigInt , integer overflow tidak lagi menjadi masalah.

Selain itu, Anda dapat bekerja dengan aman dengan stempel waktu resolusi tinggi, ID bilangan bulat besar, dan banyak lagi tanpa harus menggunakan solusi. BigInt saat ini merupakan proposal tahap 3. Setelah ditambahkan ke spesifikasi, itu akan menjadi tipe data numerik kedua dalam JavaScript, yang akan membawa jumlah total tipe data yang didukung menjadi delapan:

  • Boolean
  • Batal
  • Tidak terdefinisi
  • Nomor
  • BigInt
  • Rangkaian
  • Simbol
  • Obyek

Pada artikel ini, kita akan melihat BigInt dengan baik dan melihat bagaimana hal itu dapat membantu mengatasi keterbatasan tipe Number dalam JavaScript.

Masalah

Kurangnya tipe integer eksplisit dalam JavaScript sering membingungkan programmer yang berasal dari bahasa lain. Banyak bahasa pemrograman mendukung beberapa tipe numerik seperti float, double, integer, dan bignum, tetapi tidak demikian halnya dengan JavaScript. Dalam JavaScript, semua angka direpresentasikan dalam format titik-mengambang 64-bit presisi ganda seperti yang didefinisikan oleh standar IEEE 754-2008.

Lebih banyak setelah melompat! Lanjutkan membaca di bawah ini

Di bawah standar ini, bilangan bulat yang sangat besar yang tidak dapat direpresentasikan secara tepat secara otomatis dibulatkan. Tepatnya, tipe Number dalam JavaScript hanya dapat dengan aman mewakili bilangan bulat antara -9007199254740991 (-(2 53 -1)) dan 9007199254740991 (2 53 -1). Nilai bilangan bulat apa pun yang berada di luar rentang ini dapat kehilangan presisi.

Ini dapat dengan mudah diperiksa dengan mengeksekusi kode berikut:

 console.log(9999999999999999); // → 10000000000000000

Integer ini lebih besar dari angka terbesar yang dapat direpresentasikan JavaScript dengan primitif Number . Oleh karena itu, itu bulat. Pembulatan tak terduga dapat membahayakan keandalan dan keamanan program. Berikut contoh lain:

 // notice the last digits 9007199254740992 === 9007199254740993; // → true

JavaScript menyediakan konstanta Number.MAX_SAFE_INTEGER yang memungkinkan Anda dengan cepat mendapatkan bilangan bulat aman maksimum dalam JavaScript. Demikian pula, Anda dapat memperoleh bilangan bulat aman minimum dengan menggunakan konstanta Number.MIN_SAFE_INTEGER :

 const minInt = Number.MIN_SAFE_INTEGER; console.log(minInt); // → -9007199254740991 console.log(minInt - 5); // → -9007199254740996 // notice how this outputs the same value as above console.log(minInt - 4); // → -9007199254740996

Solusinya

Sebagai solusi untuk batasan ini, beberapa pengembang JavaScript mewakili bilangan bulat besar menggunakan tipe String . Twitter API, misalnya, menambahkan versi string ID ke objek saat merespons dengan JSON. Selain itu, sejumlah perpustakaan seperti bignumber.js telah dikembangkan untuk membuat bekerja dengan bilangan bulat besar lebih mudah.

Dengan BigInt , aplikasi tidak lagi memerlukan solusi atau pustaka untuk mewakili bilangan bulat dengan aman di luar Number.MAX_SAFE_INTEGER dan Number.Min_SAFE_INTEGER . Operasi aritmatika pada bilangan bulat besar sekarang dapat dilakukan dalam JavaScript standar tanpa risiko kehilangan presisi. Manfaat tambahan menggunakan tipe data asli di atas perpustakaan pihak ketiga adalah kinerja waktu proses yang lebih baik.

Untuk membuat BigInt , cukup tambahkan n ke akhir bilangan bulat. Membandingkan:

 console.log(9007199254740995n); // → 9007199254740995n console.log(9007199254740995); // → 9007199254740996

Atau, Anda dapat memanggil konstruktor BigInt() :

 BigInt("9007199254740995"); // → 9007199254740995n

BigInt juga dapat ditulis dalam notasi biner, oktal atau heksadesimal:

 // binary console.log(0b100000000000000000000000000000000000000000000000000011n); // → 9007199254740995n // hex console.log(0x20000000000003n); // → 9007199254740995n // octal console.log(0o400000000000000003n); // → 9007199254740995n // note that legacy octal syntax is not supported console.log(0400000000000000003n); // → SyntaxError

Ingatlah bahwa Anda tidak dapat menggunakan operator persamaan ketat untuk membandingkan BigInt dengan nomor biasa karena keduanya tidak bertipe sama:

 console.log(10n === 10); // → false console.log(typeof 10n); // → bigint console.log(typeof 10); // → number

Sebagai gantinya, Anda dapat menggunakan operator kesetaraan, yang melakukan konversi tipe implisit sebelum membandingkan operan-operannya:

 console.log(10n == 10); // → true

Semua operator aritmatika dapat digunakan di BigInt s kecuali untuk operator unary plus ( + ):

 10n + 20n; // → 30n 10n - 20n; // → -10n +10n; // → TypeError: Cannot convert a BigInt value to a number -10n; // → -10n 10n * 20n; // → 200n 20n / 10n; // → 2n 23n % 10n; // → 3n 10n ** 3n; // → 1000n let x = 10n; ++x; // → 11n --x; // → 10n

Alasan mengapa operator unary plus ( + ) tidak didukung adalah karena beberapa program mungkin mengandalkan invarian yang + selalu menghasilkan Number , atau melempar pengecualian. Mengubah perilaku + juga akan merusak kode asm.js.

Secara alami, ketika digunakan dengan operan BigInt , operator aritmatika diharapkan mengembalikan nilai BigInt . Oleh karena itu, hasil dari operator pembagian ( / ) secara otomatis terpotong. Sebagai contoh:

 25 / 10; // → 2.5 25n / 10n; // → 2n

Konversi Jenis Tersirat

Karena konversi tipe implisit dapat kehilangan informasi, operasi campuran antara BigInt s dan Number s tidak diperbolehkan. Saat mencampur bilangan bulat besar dan angka floating-point, nilai yang dihasilkan mungkin tidak dapat direpresentasikan secara akurat oleh BigInt atau Number . Perhatikan contoh berikut:

 (9007199254740992n + 1n) + 0.5

Hasil dari ekspresi ini berada di luar domain BigInt dan Number . Number dengan bagian pecahan tidak dapat dikonversi secara akurat ke BigInt . Dan BigInt yang lebih besar dari 2 53 tidak dapat secara akurat dikonversi ke Number .

Akibat pembatasan ini, tidak mungkin melakukan operasi aritmatika dengan campuran operan Number dan BigInt . Anda juga tidak dapat meneruskan BigInt ke Web API dan fungsi JavaScript bawaan yang mengharapkan Number . Mencoba melakukannya akan menyebabkan TypeError :

 10 + 10n; // → TypeError Math.max(2n, 4n, 6n); // → TypeError

Perhatikan bahwa operator relasional tidak mengikuti aturan ini, seperti yang ditunjukkan dalam contoh ini:

 10n > 5; // → true

Jika Anda ingin melakukan perhitungan aritmatika dengan BigInt dan Number , Anda harus terlebih dahulu menentukan domain di mana operasi harus dilakukan. Untuk melakukannya, cukup konversi salah satu operan dengan memanggil Number() atau BigInt() :

 BigInt(10) + 10n; // → 20n // or 10 + Number(10n); // → 20

Ketika ditemui dalam konteks Boolean , BigInt diperlakukan mirip dengan Number . Dengan kata lain, BigInt dianggap sebagai nilai kebenaran selama tidak 0n :

 if (5n) { // this code block will be executed } if (0n) { // but this code block won't }

Tidak ada konversi tipe implisit antara BigInt dan Number yang terjadi saat mengurutkan array:

 const arr = [3n, 4, 2, 1n, 0, -1n]; arr.sort(); // → [-1n, 0, 1n, 2, 3n, 4]

Operator bitwise seperti | , & , << , >> , dan ^ beroperasi pada BigInt s dengan cara yang mirip dengan Number s. Bilangan negatif diinterpretasikan sebagai komplemen dua dengan panjang tak terhingga. Operand campuran tidak diperbolehkan. Berikut beberapa contohnya:

 90 | 115; // → 123 90n | 115n; // → 123n 90n | 115; // → TypeError

Konstruktor BigInt

Seperti tipe primitif lainnya, BigInt dapat dibuat menggunakan fungsi konstruktor. Argumen yang diteruskan ke BigInt() secara otomatis dikonversi ke BigInt , jika memungkinkan:

 BigInt("10"); // → 10n BigInt(10); // → 10n BigInt(true); // → 1n

Tipe data dan nilai yang tidak dapat dikonversi memberikan pengecualian:

 BigInt(10.2); // → RangeError BigInt(null); // → TypeError BigInt("abc"); // → SyntaxError

Anda dapat langsung melakukan operasi aritmatika pada BigInt yang dibuat menggunakan konstruktor:

 BigInt(10) * 10n; // → 100n

Saat digunakan sebagai operan dari operator kesetaraan ketat, BigInt yang dibuat menggunakan konstruktor diperlakukan mirip dengan yang biasa:

 BigInt(true) === 1n; // → true

Fungsi Perpustakaan

JavaScript menyediakan dua fungsi pustaka untuk mewakili nilai BigInt sebagai bilangan bulat bertanda atau tidak bertanda:

  • BigInt.asUintN(width, BigInt) : membungkus BigInt antara 0 dan 2 lebar -1
  • BigInt.asIntN(width, BigInt) : membungkus BigInt antara -2 lebar-1 dan 2 lebar-1 -1

Fungsi-fungsi ini sangat berguna saat melakukan operasi aritmatika 64-bit. Dengan cara ini Anda dapat tetap berada dalam kisaran yang diinginkan.

Dukungan Browser Dan Transpiling

Pada saat penulisan ini, Chrome +67 dan Opera +54 sepenuhnya mendukung tipe data BigInt . Sayangnya, Edge dan Safari belum mengimplementasikannya. Firefox tidak mendukung BigInt secara default, tetapi dapat diaktifkan dengan menyetel javascript.options.bigint menjadi true di about:config . Daftar terbaru browser yang didukung tersedia di Dapatkah saya menggunakan….

Sayangnya, BigInt adalah proses yang sangat rumit, yang menimbulkan penalti kinerja run-time yang besar. Juga tidak mungkin untuk melakukan polyfill BigInt secara langsung karena proposal tersebut mengubah perilaku beberapa operator yang ada. Untuk saat ini, alternatif yang lebih baik adalah menggunakan pustaka JSBI, yang merupakan implementasi JavaScript murni dari proposal BigInt .

Pustaka ini menyediakan API yang berperilaku persis sama dengan BigInt asli. Inilah cara Anda dapat menggunakan JSBI:

 import JSBI from './jsbi.mjs'; const b1 = JSBI.BigInt(Number.MAX_SAFE_INTEGER); const b2 = JSBI.BigInt('10'); const result = JSBI.add(b1, b2); console.log(String(result)); // → '9007199254741001'

Keuntungan menggunakan JSBI adalah setelah dukungan browser meningkat, Anda tidak perlu menulis ulang kode Anda. Sebagai gantinya, Anda dapat secara otomatis mengkompilasi kode JSBI Anda ke dalam kode BigInt asli dengan menggunakan plugin babel. Selain itu, kinerja JSBI setara dengan implementasi BigInt asli. Anda dapat mengharapkan dukungan browser yang lebih luas untuk BigInt segera.

Kesimpulan

BigInt adalah tipe data baru yang dimaksudkan untuk digunakan ketika nilai integer lebih besar dari rentang yang didukung oleh tipe data Number . Tipe data ini memungkinkan kita untuk melakukan operasi aritmatika dengan aman pada bilangan bulat besar, mewakili stempel waktu resolusi tinggi, menggunakan ID bilangan bulat besar, dan banyak lagi tanpa perlu menggunakan perpustakaan.

Penting untuk diingat bahwa Anda tidak dapat melakukan operasi aritmatika dengan campuran operan Number dan BigInt . Anda harus menentukan domain tempat operasi harus dilakukan dengan mengonversi salah satu operan secara eksplisit. Selain itu, untuk alasan kompatibilitas, Anda tidak diperbolehkan menggunakan operator unary plus ( + ) pada BigInt .

Bagaimana menurutmu? Apakah menurut Anda BigInt berguna? Beri tahu kami di komentar!