一. 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控制台看下打印信息如下: