一. Unicode是什么?
Unicode是一種字符編碼方案,它為每種語言中的每個字符都設定了統一唯一的二進制編碼。以實現跨語言、跨平台進行文本轉換。
Unicode是為了解決傳統字符編碼方案的局限而產生的。
Unicode編碼的發展及詳細介紹可以看這篇文章(https://www.php.cn/js-tutorial-414753.html)。
Unicode字符編碼是用一個碼位映射一個字符,碼位值的范圍是從 U+0000 到 U+10FFFF。
碼位:一般是被格式化為十六進制數字的,零填充至少四位數,格式為 U + 前綴。
比如 A的碼位:U+0041, a的碼位:U+0061;
因為A的ASCII十進制為 65; a的ASCII的十進制為97; 我們可以在chrome瀏覽器下測試下即可:
'A'.charCodeAt(); // 打印65
因此 字符 A 十進制為65,轉換成十六進制就是41了,十六進制轉十進制的方法為 65 = 4 * 16 + 1; 因此變成Unicode碼位的話: U+0041了。
Unicode最前面的65536個字符位,稱為零號平面,它的碼位范圍是從 U+0000 到 U+FFFF; 我們最常見的字符都在這里面了。
Unicode轉義
1. 16進制轉義
"A" 轉義為:'\x41'; "a" 轉義為: '\x61';
2. Unicode轉義
A的Unicode碼位為: 'U+0041'; 因此 字符A的Unicode的轉義就變成了 '\u0041'; 我們可以在chrome控制台打印下就知道了。
在ECMAScript6中,引入了一種新的轉義序列:Unicode碼位轉義: 比如:'\u{41}'; 使用大括號對16進制數字,在大括號之間可以使用最多6個十六進制數字。
字符串方法中的Unicode
1. String.fromCharCode()
String.fromCharCode() 方法可以將一個碼位轉換為字符,但是它只適用於BMP范圍內的碼位(即從 U+0000 到 U+FFFF)。如果將它用於轉換超過BMP外的碼位,將不會得到想要的結果。
fromCharCode()可以接受一個指定的Unicode的值,然后返回一個字符串。該方法是String的靜態方法,字符串中的每個字符都由單獨的Unicode數字編碼指定。基本語法如下所示:
String.fromCharCode(n1, n2, ......nx);
比如如下代碼:
var n = String.fromCharCode(72,69,76,76,79); console.log(n); // 打印的值為:"HELLO"
String.fromCharCode() 的缺點是:
對於在 U+0000 到 U+FFFF 范圍之外的碼位是獲取不到結果的,我們看下:
String.fromCharCode(0x1F4A9);
打印的結果如下:

解決的方法當然也有,但是方法也不是很好,但是幸運的是,ES6中引入了 String.fromCodePoint(codePoint). 該方法的優點是可以用於任何的Unicode編碼,它是范圍更廣,是從 U+0000 到 U+10FFFF; 我們可以繼續使用該方法測試下上面的demo;
String.fromCodePoint(0x1F4A9);
在chrome瀏覽器下執行的結果如下所示:

2. String.prototype.charAt(position)
該方法是用來檢索包含字符串中的第一個字符。
比如如下代碼:
'abcdeb'.charAt(1); // 打印 b
3. String.prototype.charCodeAt(position)
該方法的含義是:從字符串中獲取碼位, 檢索字符串中第一個字符的碼位。
比如如下代碼:
'ABC'.charCodeAt(1); // 輸出結果為66;
如上是字符串 'ABC'; 找到第2個字符串的碼位。
二:JS中Unicode編碼與String相互轉換
1. 字符串轉Unicode
第一種方式:
var str='\u6211\u662f\u4e2d\u56fd\u4ebaChina'; var ret1 = eval("'" + str + "'"); console.log(ret1); // 打印出:我是中國人China
第二種方式:
var str='\u6211\u662f\u4e2d\u56fd\u4ebaChina'; var ret2 = (new Function("return '" + str + "'"))(); console.log(ret2); // 打印出:我是中國人China
第三種方式:
var str='\u6211\u662f\u4e2d\u56fd\u4ebaChina'; var ret3 = unescape(str.replace(/\u/g, '%u')); console.log(ret3); // 打印出:我是中國人China
2. Unicode轉字符串
function string2unicode(str) { var html = ''; for (let i = 0; i < str.length; i++) { console.log(str.charCodeAt(i)) html += "\\u" + str.charCodeAt(i).toString(16); } return html; } var str = "我是中國人"; var s2u = string2unicode(str); console.log(s2u); // 打印出: \u6211\u662f\u4e2d\u56fd\u4eba console.log(eval("'"+s2u+"'")); // 輸出:我是中國人
如上代碼,使用的語法是:number.toString(radix);
radix參數可選;它值可以是2、8、16,表示以多少進制來顯示。
更多了解可以看對應的API(https://www.runoob.com/jsref/jsref-tostring-number.html)
如下代碼演示:
var num = 15; var a = num.toString(); var b = num.toString(2); var c = num.toString(8); var d = num.toString(16); console.log(a); // 15 console.log(b); // 1111 console.log(c); // 17 console.log(d); // f
如上字符串轉Unicode的方法 string2unicode 有缺陷的,比如中文里面包含英文的話,就不行了,請看如下代碼:
function string2unicode(str) { var html = ''; for (let i = 0; i < str.length; i++) { html += "\\u" + str.charCodeAt(i).toString(16); } return html; } var str = "我是中國人a"; var s2u = string2unicode(str); console.log(s2u); // 打印結果為: \u6211\u662f\u4e2d\u56fd\u4eba\u61 console.log(eval("'"+s2u+"'"));
如上代碼就報錯了,因為JS自身的Unicode轉字符串不能識別不足4位的unicode。因此我們要對 string2unicode方法改進一下。
function string2unicode(str) { var html = ''; var rets = ''; for (let i = 0; i < str.length; i++) { // 獲取碼位 var c1 = str.charCodeAt(i); // 轉換成16進制 var c16 = c1.toString(16); // 0xf 代表16進制f,轉換成10進制就是15 if (c1 < 0xf) { html += "\\u" + "000" + c16; } else if (c1 < 0xff) { html += "\\u" + "00" + c16; } else if (c1 < 0xfff) { html += "\\u" + '0' + c16; } else { html += "\\u" + c16; } } rets += html; return rets; } var str = "我是中國人a"; var s2u = string2unicode(str); console.log(s2u); // 打印結果為: \u6211\u662f\u4e2d\u56fd\u4eba\u61 console.log(eval("'"+s2u+"'")); // 打印: 我是中國人a
我們可以在chrome控制台看下打印信息如下:

