首頁 web前端 js教程 JavaScript語言對Unicode字元集的支援詳解_基礎知識

JavaScript語言對Unicode字元集的支援詳解_基礎知識

May 16, 2016 pm 04:23 PM
javascript unicode 字元集

上個月,我做了一次分享,詳細介紹了Unicode字元集,以及JavaScript語言對它的支援。下面就是這次分享的講稿。

 一、Unicode是什麼?

  Unicode源自於一個很簡單的想法:將全世界所有的字元包含在一個集合裡,電腦只要支援這一個字元集,就能顯示所有的字符,再也不會有亂碼了。

  它從0開始,為每個符號指定一個編號,這叫做"碼點"(code point)。例如,碼點0的符號就是null(表示所有二進位位元都是0)。

複製代碼 代碼如下:
U 0000 = null

  上式中,U 表示緊接在後面的十六進位數是Unicode的碼點。

  目前,Unicode的最新版本是7.0版,總共收入了109449個符號,其中的中日韓文字為74500個。可以近似認為,全世界現有的符號當中,三分之二以上來自東亞文字。例如,中文"好"的碼點是十六進位的597D。

複製程式碼 程式碼如下:
U 597D = 好

U 597D = 好

  這麼多符號,Unicode不是一次性定義的,而是分區定義。每個區可以存放65536個(216)字符,稱為一個平面(plane)。目前,總共有17個(25)平面,也就是說,整個Unicode字元集的大小現在是221。

  最前面的65536個字元位,稱為基本平面(縮寫BMP),它的碼點範圍是從0一直到216-1,寫成16進位就是從U 0000到U FFFF。所有最常見的字元都放在這個平面,這是Unicode最先定義和公佈的一個平面。

  剩下的字元都放在輔助平面(縮寫SMP),碼點範圍從U 010000一直到U 10FFFF。

 二、UTF-32與UTF-8

  Unicode只規定了每個字元的碼點,到底用什麼樣的字節序表示這個碼點,就涉及到編碼方法。

  最直觀的編碼方法是,每個碼點使用四個位元組表示,位元組內容一一對應碼點。這種編碼方法就叫做UTF-32。例如,碼點0就用四個位元組的0表示,碼點597D就在前面加兩個位元組的0。 複製程式碼
程式碼如下:U 0000 = 0x0000 0000U 59700

  UTF-32的優點在於,轉換規則簡單直觀,尋找效率高。缺點在於浪費空間,同樣內容的英文文本,它會比ASCII編碼大四倍。這個缺點很致命,導致實際上沒有人使用這種編碼方法,HTML 5標準就明文規定,網頁不得編碼成UTF-32。

  人們真正需要的是一種節省空間的編碼方法,這導致了UTF-8的誕生。 UTF-8是一種變長的編碼方法,字元長度從1個位元組到4個位元組不等。越是常用的字符,位元組越短,最前面的128個字符,只使用1個位元組表示,與ASCII碼完全相同。

編號範圍位元組0x0000 - 0x007F10x0080 - 0x07FF20x0800 - 0xFFFF30x010000 - 0x10FFFF4

  由於UTF-8這種節省空間的特性,導致它成為網路上最常見的網頁編碼。不過,它跟今天的主題關係不大,我就不深入了,具體的轉碼方法,可以參考《字符編碼筆記》

 三、UTF-16簡介

  UTF-16編碼介於UTF-32與UTF-8之間,同時結合了定長與變長兩種編碼方法的特性。

  它的編碼規則很簡單:基本平面的字元佔用2個位元組,輔助平面的字元佔用4個位元組。也就是說,UTF-16的編碼長度要麼是2個位元組(U 0000到U FFFF),要麼是4個位元組(U 010000到U 10FFFF)。

  於是就有一個問題,當我們遇到兩個字節,怎麼看出它本身是一個字符,還是需要跟其他兩個字節放在一起解讀?

  說來很巧妙,我也不知道是不是故意的設計,在基本平面內,從U D800到U DFFF是一個空段,即這些碼點不對應任何字符。因此,這個空段可以用來映射輔助平面的字元。

  具體來說,輔助平面的字元位元共有220個,也就是說,對應這些字元至少需要20個二進位位元。 UTF-16將這20位元拆成兩半,前10位元映射在U D800到U DBFF(空間大小210),稱為高位元(H),後10位元映射在U DC00到U DFFF(空間大小210) ,稱為低位(L)。這意味著,一個輔助平面的字符,被拆成兩個基本平面的字符表示。

  所以,當我們遇到兩個字節,發現它的碼點在U D800到U DBFF之間,就可以斷定,緊跟在後面的兩個字節的碼點,應該在U DC00到U DFFF之間,這四個位元組必須放在一起解讀。

 四、UTF-16的轉碼公式

  Unicode碼點轉成UTF-16的時候,先區分這是基本平面字符,還是輔助平面字符。如果是前者,直接將碼點轉為對應的十六進位形式,長度為兩個位元組。

複製代碼 代碼如下:
U 597D = 0x597D

  如果是輔助平面字符,Unicode 3.0版給出了轉碼公式。

複製程式碼 程式碼如下:
H = Math.floor((c-0x10000) / 0x4000) = (c - 0x10000) % 0x400 0xDC00

  以字符為例,它是一個輔助平面字符,碼點為U 1D306,將其轉為UTF-16的計算過程如下。

複製程式碼 程式碼如下:
H = Math.floor((0x1D306-0x10000)/0x1000)/0x = 0xD834L = (0x1D306-0x10000) % 0x400 0xDC00 = 0xDF06

  所以,字元的UTF-16編碼就是0xD834 DF06,長度為四個位元組。

 五、JavaScript使用哪一種編碼?

  JavaScript語言採用Unicode字元集,但只支援一種編碼方法。

  這種編碼既不是UTF-16,也不是UTF-8,更不是UTF-32。上面那些編碼方法,JavaScript都不用。

  JavaScript用的是UCS-2!

 六、UCS-2編碼

  怎麼突然殺出一個UCS-2?這就需要講一點歷史。

  網路還沒出現的年代,曾經有兩個團隊,不約而同想搞統一字符集。一個是1989年成立的Unicode團隊,另一個是更早的、1988年成立的UCS團隊。等到他們發現了對方的存在,很快就達成一致:世界上不需要兩套統一字符集。

  1991年10月,兩個團隊決定合併字元集。也就是說,從今以後只發布一套字元集,就是Unicode,並且修訂先前發布的字元集,UCS的碼點將與Unicode完全一致。

  當時的實際情況是,UCS的開發進度快於Unicode,早在1990年,就公佈了第一套編碼方法UCS-2,使用2個位元組表示已經有碼點的字元。 (那時只有一個平面,就是基本平面,所以2個位元組就夠用了。)UTF-16編碼遲至1996年7月才公佈,明確宣布是UCS-2的超集,即基本平面字符沿用UCS-2編碼,輔助平面字元定義了4個位元組的表示方法。

  兩者的關係簡單說,就是UTF-16取代了UCS-2,或者說UCS-2整合進了UTF-16。所以,現在只有UTF-16,沒有UCS-2。

 七、JavaScript的誕生背景

  那麼,為什麼JavaScript不選擇更高級的UTF-16,而用了已經被淘汰的UCS-2呢?

  答案很簡單:非不想也,是不能也。因為在JavaScript語言出現的時候,還沒有UTF-16編碼。

  1995年5月,Brendan Eich用了10天設計了JavaScript語言;10月,第一個解釋引擎問世;隔年11月,Netscape正式向ECMA提交語言標準(整個過程詳見《 JavaScript誕生記》)。比較UTF-16的發佈時間(1996年7月),就會明白Netscape公司那時沒有其他選擇,只有UCS-2一種編碼方法可用!

 八、JavaScript字元函數的限制

  由於JavaScript只能處理UCS-2編碼,造成所有字符在這門語言中都是2個字節,如果是4個字節的字符,會當作兩個雙字節的字符處理。 JavaScript的字元函數都受到這一點的影響,無法傳回正確結果。

  還是以字元為例,它的UTF-16編碼是4個位元組的0xD834 DF06。問題就來了,4個位元組的編碼不屬於UCS-2,JavaScript不認識,只會把它看作單獨的兩個字元U D834和U DF06。前面說過,這兩個碼點是空的,所以JavaScript會認為是兩個空字元組成的字串!

  上面程式碼表示,JavaScript認為字符的長度是2,取到的第一個字符是空字符,取到的第一個字符的碼點是0xDB34。這些結果都不正確!

  解決這個問題,必須對碼點做一個判斷,然後手動調整。下面是正確的遍歷字串的寫入方法。

複製程式碼 程式碼如下:
while ( index = 0xD800 && charCode

  上面程式碼表示,遍歷字串的時候,必須對碼點做一個判斷,只要落在0xD800到0xDBFF的區間,就要連同後面2個位元組一起讀取。

  類似的問題存在於所有的JavaScript字元操作函數。

String.prototype.replace()String.prototype.substring()String.prototype.slice()...

  上面的函數都只對2位元組的碼點有效。要正確處理4位元組的碼點,就必須逐一部署自己的版本,判斷一下目前字元的碼點範圍。

 九、ECMAScript 6

  JavaScript的下一個版本ECMAScript 6(簡稱ES6),大幅增強了Unicode支持,基本上解決了這個問題。

  (1)正確辨識字元

  ES6可以自動辨識4位元組的碼點。因此,遍歷字串就簡單多了。

複製程式碼 程式碼如下:
for (let s of string ) { //}

  但是,為了保持相容,length屬性還是原來的行為方式。為了得到字串的正確長度,可以用下面的方式。

複製程式碼 程式碼如下:
Array.from(string).length
Array.from(string).length

  (2)碼點表示法

  JavaScript允許直接用碼點表示Unicode字符,寫法是"斜杠 u 碼點"。

複製程式碼
程式碼如下:
'好' === 'u597D' // true

'好' === 'u597D' // true

'好' === 'u597D' // true

'好' === 'u597D' // true

'好' === 'u597D' // true

  但是,這種表示法對4位元組的碼點無效。 ES6修正了這個問題,只要將碼點放在大括號內,就能正確辨識。

  (3)字串處理函數

  ES6新增了幾個專門處理4位元組碼點的函數。

String.fromCodePoint():從Unicode碼點傳回對應字元String.prototype.codePointAt():從字元傳回對應的碼點String.prototype.at():傳回字串給定位置的字元

  (4)正規表示式

  ES6提供了u修飾符,對正規表示式添加4字節碼點的支援。

  (5)Unicode正規化

  Unicode提供了兩種表示法。一種是帶有附加符號的單個字符,即一個碼點表示一個字符,例如Ǒ的碼點是U 01D1;另一種是將附加符號單獨作為一個碼點,與主體字符複合顯示,即兩個碼點表示一個字符,例如Ǒ可以寫成O(U 004F) ˇ(U 030C)。



複製程式碼


程式碼如下:

// 方法一

'u01D1'

// 'Ǒ'

  這兩種表示方法,視覺和語意都完全一樣,理應作為等同情況處理。但是,JavaScript無法辨別。



複製程式碼

程式碼如下:

'u01D1'==='u004Fu030C' //false   ES6提供了normalize方法,允許"Unicode正規化"
,即將兩種方法轉為相同的序列。 複製程式碼 程式碼如下:
'u01D1'.normalize() === 'u004Fu030C'.normalize() // true

  關於ES6的更多介紹,請看《ECMAScript 6入門》

  ==========================

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何使用WebSocket和JavaScript實現線上語音辨識系統 如何使用WebSocket和JavaScript實現線上語音辨識系統 Dec 17, 2023 pm 02:54 PM

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術 WebSocket與JavaScript:實現即時監控系統的關鍵技術 Dec 17, 2023 pm 05:30 PM

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何使用WebSocket和JavaScript實現線上預約系統 如何使用WebSocket和JavaScript實現線上預約系統 Dec 17, 2023 am 09:39 AM

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

如何利用JavaScript和WebSocket實現即時線上點餐系統 如何利用JavaScript和WebSocket實現即時線上點餐系統 Dec 17, 2023 pm 12:09 PM

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

JavaScript與WebSocket:打造高效率的即時天氣預報系統 JavaScript與WebSocket:打造高效率的即時天氣預報系統 Dec 17, 2023 pm 05:13 PM

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

簡易JavaScript教學:取得HTTP狀態碼的方法 簡易JavaScript教學:取得HTTP狀態碼的方法 Jan 05, 2024 pm 06:08 PM

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

javascript如何使用insertBefore javascript如何使用insertBefore Nov 24, 2023 am 11:56 AM

用法:在JavaScript中,insertBefore()方法用於在DOM樹中插入一個新的節點。這個方法需要兩個參數:要插入的新節點和參考節點(即新節點將要插入的位置的節點)。

深入了解PHP:JSON Unicode轉中文的實作方法 深入了解PHP:JSON Unicode轉中文的實作方法 Mar 05, 2024 pm 02:48 PM

深入了解PHP:JSONUnicode轉中文的實作方法在開發中,我們經常會遇到需要處理JSON資料的情況,而JSON中的Unicode編碼在一些場景下會為我們帶來一些問題,特別是當需要將Unicode編碼轉換為中文字元時。在PHP中,有一些方法可以幫助我們實現這個轉換過程,以下將介紹常用的方法,並提供具體的程式碼範例。首先,讓我們先來了解一下JSON中Un

See all articles