Panduan Penting Untuk Jenis Data Terbaru JavaScript: BigInt
Diterbitkan: 2022-03-10Number
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.
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)
: membungkusBigInt
antara 0 dan 2 lebar -1 -
BigInt.asIntN(width, BigInt)
: membungkusBigInt
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!