1. Apa itu Unicode?
Unicode berasal dari ide yang sangat sederhana: untuk memasukkan semua karakter di dunia dalam koleksi. Selama komputer mendukung set karakter ini, ia dapat menampilkan semua karakter, dan tidak akan ada kode yang kacau lagi.
Dimulai pada 0 dan menentukan angka untuk setiap simbol, yang disebut "codepoint". Misalnya, simbol titik kode 0 adalah nol (menunjukkan bahwa semua bit biner adalah 0).
Salin kode sebagai berikut: U+0000 = NULL
Dalam rumus di atas, U+ berarti bahwa nomor heksadesimal segera berikut adalah titik kode Unicode.
Saat ini, versi terbaru Unicode adalah versi 7.0, dengan total 109.449 simbol, di mana 74.500 termasuk dalam karakter Cina, Jepang dan Korea. Kira-kira dapat dipercaya bahwa lebih dari dua pertiga dari simbol yang ada di dunia berasal dari karakter Asia Timur. Misalnya, titik kode untuk "baik" Cina adalah hexadecimal 597d.
Salin kode sebagai berikut: u+597d = ok
Dengan begitu banyak simbol, Unicode tidak didefinisikan pada satu waktu, tetapi definisi partisi. Setiap area dapat menyimpan 65.536 (216) karakter, disebut pesawat. Saat ini, ada 17 (25) bidang secara total, yang berarti bahwa ukuran seluruh set karakter Unicode sekarang 221.
Bit karakter 65536 pertama disebut bidang dasar (Singkat BMP), dan titik kode mereka berkisar dari 0 hingga 216-1. Ditulis dalam hexadecimal adalah dari U+0000 ke U+ffff. Semua karakter yang paling umum ditempatkan di bidang ini, yang merupakan bidang pertama yang didefinisikan dan diterbitkan Unicode.
Karakter yang tersisa ditempatkan di bidang tambahan (SMP disingkat), dan titik kode berkisar dari U+010000 hingga U+10FFFF.
2. UTF-32 dan UTF-8
Unicode hanya menentukan titik kode dari setiap karakter. Jenis urutan byte apa yang digunakan untuk mewakili titik kode ini, yang melibatkan metode pengkodean.
Metode pengkodean yang paling intuitif adalah bahwa setiap titik kode diwakili oleh empat byte, dan konten byte sesuai dengan titik kode satu per satu. Metode pengkodean ini disebut UTF-32. Misalnya, titik kode 0 diwakili oleh empat byte 0, dan titik kode 597D ditambahkan dengan dua byte 0 di depan.
Salin kode sebagai berikut: U+0000 = 0x0000 0000U+597D = 0x0000 597D
Keuntungan dari UTF-32 adalah bahwa aturan konversi sederhana dan intuitif dan efisiensi pencarian tinggi. Kerugiannya adalah bahwa itu adalah ruang yang terbuang, dan teks bahasa Inggris dengan konten yang sama akan empat kali lebih besar dari pengkodean ASCII. Kerugian ini berakibat fatal, sehingga tidak ada yang benar -benar menggunakan metode pengkodean ini. Standar HTML5 secara eksplisit menetapkan bahwa halaman web tidak boleh dikodekan menjadi UTF-32.
Yang benar-benar dibutuhkan orang adalah metode pengkodean hemat ruang, yang mengarah pada kelahiran UTF-8. UTF-8 adalah metode pengkodean panjang variabel, dengan panjang karakter mulai dari 1 byte hingga 4 byte. Karakter yang lebih umum digunakan, semakin pendek byte. 128 karakter pertama diwakili oleh hanya 1 byte, yang persis sama dengan kode ASCII.
Bytes Rentang Nomor 0x0000 - 0x007f10x0080 - 0x07ff20x0800 - 0xfff30x010000 - 0x10ffff4
Karena fitur hemat ruang UTF-8, ini telah menjadi pengkodean web yang paling umum di internet. Namun, itu tidak ada hubungannya dengan topik hari ini, jadi saya tidak akan membahasnya. Untuk metode transcoding spesifik, silakan merujuk ke "Catatan Pengkodean Karakter" yang saya tulis bertahun -tahun yang lalu.
AKU AKU AKU. Pengantar UTF-16
Pengkodean UTF-16 adalah antara UTF-32 dan UTF-8, dan menggabungkan karakteristik dua metode pengkodean: panjang tetap dan panjang variabel.
Aturan pengkodeannya sederhana: karakter dalam bidang dasar menempati 2 byte, dan karakter dalam bidang tambahan menempati 4 byte. Dengan kata lain, panjang pengkodean UTF-16 adalah 2 byte (U+0000 ke U+FFFF) atau 4 byte (U+010000 ke U+10FFFF).
Jadi ada pertanyaan: Ketika kita menemukan dua byte, bagaimana kita melihat bahwa itu adalah karakter itu sendiri, atau apakah kita perlu menafsirkannya dengan dua byte lainnya?
Ini sangat pintar, dan saya tidak tahu apakah itu disengaja. Di bidang dasar, dari U+D800 ke U+DFFF adalah segmen kosong, yaitu, titik kode ini tidak sesuai dengan karakter apa pun. Oleh karena itu, segmen kosong ini dapat digunakan untuk memetakan karakter bidang tambahan.
Secara khusus, ada 220 bit karakter dalam bidang tambahan, yang berarti bahwa setidaknya 20 bit biner diperlukan untuk karakter ini. UTF-16 membagi 20 bit ini menjadi dua. 10 bit pertama dipetakan dalam U+D800 ke U+DBFF (ukuran ruang 210), yang disebut bit tinggi (h), dan 10 bit terakhir dipetakan dalam U+DC00 ke U+DFFF (ukuran ruang 210), yang disebut bit rendah (L). Ini berarti bahwa karakter bidang tambahan dipecah menjadi dua bidang dasar representasi karakter.
Oleh karena itu, ketika kita menemukan dua byte dan menemukan bahwa titik kodenya adalah antara U+D800 dan U+DBFF, kita dapat menyimpulkan bahwa titik kode segera mengikuti kedua byte harus antara U+DC00 dan U+DFFF. Keempat byte ini harus ditafsirkan bersama.
Iv. Formula Transkode UTF-16
Saat mengonversi kode kode unicode ke UTF-16, pertama-tama bedakan apakah ini adalah karakter datar dasar atau karakter datar tambahan. Jika yang pertama, konversi secara langsung titik kode ke bentuk heksadesimal yang sesuai, dengan panjang dua byte.
Salin kode sebagai berikut: u+597d = 0x597d
Jika itu adalah karakter datar tambahan, Unicode Versi 3.0 memberikan rumus transcoding.
Salin kode kode sebagai berikut: h = math.floor ((c -0x10000) / 0x400) + 0xd800l = (c - 0x10000) % 0x400 + 0xdc00
Mengambil karakter sebagai contoh, ini adalah karakter bidang tambahan dengan titik kode U+1D306. Proses perhitungan mengubahnya menjadi UTF-16 adalah sebagai berikut.
Salin kode kode sebagai berikut: h = math.floor ((0x1d306-0x10000)/0x400)+0xd800 = 0xd834l = (0x1d306-0x10000) % 0x400+0xdc00 = 0xdf06
Oleh karena itu, pengkodean UTF-16 dari karakter adalah 0xD834 DF06, dengan panjang empat byte.
5. Pengkodean mana yang digunakan dalam JavaScript?
Bahasa JavaScript menggunakan set karakter Unicode, tetapi hanya mendukung satu metode pengkodean.
Pengkodean ini bukan UTF-16, atau UTF-8, atau UTF-32. JavaScript tidak menggunakan metode pengkodean di atas.
JavaScript menggunakan UCS-2!
Vi. Pengkodean UCS-2
Mengapa UCS-2 tiba-tiba muncul? Ini membutuhkan sedikit sejarah.
Di era ketika internet belum muncul, ada dua tim yang keduanya ingin membuat set karakter terpadu. Salah satunya adalah tim Unicode yang didirikan pada tahun 1988, dan yang lainnya adalah tim UCS yang didirikan pada tahun 1989. Ketika mereka menemukan keberadaan satu sama lain, mereka dengan cepat mencapai kesepakatan: tidak perlu untuk dua set karakter terpadu di dunia.
Pada Oktober 1991, kedua tim memutuskan untuk menggabungkan set karakter. Dengan kata lain, hanya satu set set karakter yang akan dirilis mulai sekarang, yaitu Unicode, dan set karakter yang dirilis sebelumnya akan direvisi, dan titik kode UCS akan persis sama dengan Unicode.
Kemajuan pengembangan UCS lebih cepat daripada Unicode. Pada tahun 1990, metode pengkodean pertama UCS-2 diumumkan, menggunakan 2 byte untuk mewakili karakter dengan poin kode. ;
Sederhananya, hubungan antara keduanya adalah bahwa UTF-16 menggantikan UCS-2, atau UCS-2 diintegrasikan ke dalam UTF-16. Jadi, sekarang hanya ada UTF-16, tidak ada UCS-2.
7. Latar belakang kelahiran JavaScript
Jadi, mengapa JavaScript tidak memilih UTF-16 yang lebih canggih, tetapi menggunakan UCS-2 yang sudah usang?
Jawabannya sangat sederhana: bukan karena Anda tidak mau, Anda tidak bisa. Karena ketika bahasa JavaScript muncul, tidak ada pengkodean UTF-16.
Pada Mei 1995, Brendan Eich merancang bahasa JavaScript dalam 10 hari; Pada bulan Oktober, mesin penjelasan pertama dirilis; Pada bulan November tahun berikutnya, Netscape secara resmi mengajukan standar bahasa kepada ECMA (lihat "Kelahiran JavaScript" untuk perincian tentang seluruh proses). Dengan membandingkan tanggal rilis UTF-16 (Juli 1996), Anda akan memahami bahwa Netscape tidak punya pilihan lain pada waktu itu, hanya metode pengkodean UCS-2 yang tersedia!
8. Keterbatasan Fungsi Karakter JavaScript
Karena JavaScript hanya dapat menangani pengkodean UCS-2, semua karakter adalah 2 byte dalam bahasa ini. Jika mereka 4 byte, mereka akan diperlakukan sebagai dua byte ganda. Fungsi karakter JavaScript dipengaruhi oleh ini dan tidak dapat mengembalikan hasil yang benar.
Ambil karakter sebagai contoh, pengkodean UTF-16-nya adalah 4 byte 0xD834DF06. Masalahnya adalah bahwa pengkodean 4 byte bukan milik UCS-2, dan JavaScript tidak mengenalinya, dan hanya akan menganggapnya sebagai dua karakter terpisah U+D834 dan U+DF06. Seperti yang disebutkan sebelumnya, kedua titik kode ini kosong, jadi JavaScript akan menganggapnya sebagai string yang terdiri dari dua karakter kosong!
Kode di atas menunjukkan bahwa JavaScript percaya bahwa panjang karakter adalah 2, karakter pertama yang diperoleh adalah karakter nol, dan titik kode karakter pertama yang diperoleh adalah 0xDB34. Hasil ini tidak benar!
Untuk mengatasi masalah ini, Anda harus membuat penilaian pada titik kode dan kemudian menyesuaikannya secara manual. Berikut ini adalah cara yang benar untuk menulis string.
Salin kode kode sebagai berikut: while (++ index <length) {// ... if (charcode> = 0xd800 && charcode <= 0xdbff) {output.push (karakter+string.charat (++ index)); } else {output.push (karakter); }}
Kode di atas menunjukkan bahwa saat melintasi string, Anda harus membuat penilaian pada titik kode. Selama jatuh dalam interval antara 0xd800 dan 0xdbff, itu harus dibaca bersama dengan 2 byte berikutnya.
Masalah serupa ada di semua fungsi manipulasi karakter JavaScript.
String.prototype.replace ()
String.prototype.substring ()
String.prototype.slice ()
...
Semua fungsi di atas hanya valid hanya untuk poin kode 2-byte. Untuk memproses poin kode 4-byte dengan benar, Anda harus menggunakan versi Anda sendiri satu per satu dan menilai kisaran titik kode dari karakter saat ini.
9. Ecmascript 6
Versi berikutnya dari JavaScript, ECMascript 6 (singkatnya ES6), telah sangat meningkatkan dukungan Unicode, pada dasarnya menyelesaikan masalah ini.
(1) Identifikasi karakter dengan benar
ES6 dapat secara otomatis mengenali titik kode 4-byte. Karena itu, jauh lebih mudah untuk melintasi string.
Salin kode sebagai berikut: untuk (let s string) {// ...}
Namun, untuk mempertahankan kompatibilitas, atribut panjang masih merupakan perilaku asli. Untuk mendapatkan panjang string yang benar, Anda dapat menggunakan metode berikut.
Salin kode sebagai berikut: array.from (string) .length
(2) Representasi titik kode
JavaScript memungkinkan karakter Unicode diwakili secara langsung dengan titik kode, yang ditulis sebagai "Backslash + U + Code Points".
Salin kode sebagai berikut: 'ok' === '/u597d' // true
Namun, notasi ini tidak valid untuk poin kode 4-byte. ES6 memperbaiki masalah ini dan dapat mengidentifikasinya dengan benar selama titik kode ditempatkan di kawat gigi keriting.
(3) Fungsi pemrosesan string
ES6 telah menambahkan beberapa fungsi baru yang secara khusus menangani poin kode 4-byte.
String.FromCodePoint (): Kembalikan karakter yang sesuai dari titik kode unicode
String.prototype.codepointat (): Mengembalikan titik kode yang sesuai dari karakter
String.prototype.at (): Mengembalikan karakter pada posisi string yang diberikan
(4) Ekspresi reguler
ES6 menyediakan pengubah U untuk menambahkan titik kode 4-byte ke ekspresi reguler.
(5) regularisasi unicode
Beberapa karakter memiliki simbol tambahan selain huruf. Misalnya, di pinyin Cina, nada pada huruf adalah simbol tambahan. Simbol nada sangat penting bagi banyak bahasa Eropa.
Unicode menyediakan dua metode representasi. Salah satunya adalah karakter tunggal dengan simbol tambahan, yaitu, titik kode mewakili karakter, seperti titik kode ǒ adalah U+01D1; Yang lainnya adalah menggunakan simbol tambahan sebagai titik kode dan menampilkannya dalam kombinasi dengan karakter utama, yaitu dua titik kode mewakili karakter, seperti ǒ dapat ditulis sebagai O (U+004F)+ˇ (U+030C).
Salin kode sebagai berikut: // Metode 1 '/u01d1' // 'ǒ' // Metode 2 '/u004f/u030c' // 'ǒ'
Kedua metode representasi ini persis sama dalam penglihatan dan semantik dan harus diperlakukan sebagai situasi yang setara. Namun, JavaScript tidak tahu.
Salin kode sebagai berikut: '/u01d1' === '/u004f/u030c' // false
ES6 memberikan metode normalisasi, memungkinkan "regularisasi unicode", yaitu, mengubah kedua metode menjadi urutan yang sama.
Salin kode sebagai berikut: '/u01d1'.normalize () ===' /U004f/u030c'.normalize () // true
Untuk lebih lanjut pengantar ES6, silakan lihat "Hiburan Ecmascript 6".