这篇文章介绍ES6中针对unicode字符串的几个新增函数。
String.prototype.codePointAt
函数类型:(index?: number)=> number|undefined
codePointAt
是一个原型函数,它根据传入的index
参数,返回字符串中位于该处的字符的码点(code point)值。这个方法可以识别utf-16中的4字节码点,支持的范围比原型函数charCodeAt
更广,charCodeAt
只能识别2字节的基本平面字符(BMP)。另外,当index
越界时,codePointAt
返回undefined
,charCodeAt
返回NaN
。除了这两点之外,
codePointAt
和charCodeAt
的结果基本一致:index
的参数默认值都为0
当字符处于基本平面字符集的时候,二者返回的结果是一样的。
const str = 'abc'; //字符 'a' 位于基本平面字符集中 console.log(str.codePointAt(0));//97 //index默认值为0 console.log(str.codePointAt());//97 //index越界时,返回undefined console.log(str.codePointAt(5));//undefined console.log(str.charCodeAt(0));//97 //index默认值为0 console.log(str.charCodeAt());//97 //index越界时,返回NaN console.log(str.charCodeAt(5));//NaN
当字符处于辅助平面字符集的时候,
codePointAt
能够正确识别,并返回对应字符的码点(code point)。charCodeAt
不能正确识别,只能返回当前位置的2字节字符的码点。比如,对于辅助平面的高音字符𝄞,它由两个2字节的基本平面字符
0xd834
和0xdd1e
表示。当我们对𝄞使用
charCodeAt
时,只能得到对应位置的码点。const str = '\ud834\udd1e'; //辅助平面字符 高音字符 𝄞 console.log(str.charCodeAt(0).toString(16)); //d834 console.log(str.charCodeAt(1).toString(16)); //dd1e
当我们使用
codePointAt
时,可以得到𝄞的码点0x1d11e
。console.log(str.codePointAt(0).toString(16)); //1d11e //当index为1时,'\udd1e'后面没有另一个代码单元,被认为只是一个2字节的字符,而非是一对代码单元,所以此时只返回'\udd1e'的码点,而非'\ud834\udd1e'的码点 console.log(str.codePointAt(1).toString(16)); //dd1e
String.fromCodePoint
函数类型:
(...codePoints: number[])=> string
静态函数
fromCodePoint
是根据传入的unicode码点返回对应的字符串,和fromCharCode
相比,它支持直接传入辅助平面的码点值了。还是以高音符号𝄞为例,使用fromCodePoint
可以直接传入码点值0x1d11e
,而fromCharCode
值需要传入0xd834
和0xdd1e
。console.log(String.fromCodePoint(0x1d11e)); //𝄞 console.log(String.fromCodePoint(0xd834, 0xdd1e)); //𝄞 console.log(String.fromCharCode(0x1d11e)); //턞 不能正确识别,乱码 console.log(String.fromCharCode(0xd834, 0xdd1e)); //𝄞
对于基本平面的字符,
fromCodePoint
和fromCharCode
结果是一样的。console.log(String.fromCodePoint(97)); //'a' console.log(String.fromCodePoint(97, 98)); //'ab' console.log(String.fromCodePoint()); //'' console.log(String.fromCharCode(97)); //'a' console.log(String.fromCharCode(97, 98)); //'ab' console.log(String.fromCharCode()); //''
String.prototype.normalize
函数类型:
(form:'NFC'|'NFD'|'NFKC'|'NFKD')=>string
原型函数
normalize
接受一个指定正规化(如果你不明白NFC、NFD等的意义,点一下)形式的参数form
,form
默认值为'NFC'(Normalization Form Canonical Composition,以标准等价方式来分解,然后以标准等价重组),返回正规化的字符串。unicode对合成符号(字符中的字母带有声调等附加符号)提供了两种表示方式,一种是使用一个unicode码点表示,一种是将合成字符中的字母与附加符号组合,使用两个码点,比如
ń
是一个合成符号,我们既可以使用一个码点0x0144
表示,也可以使用两个码点0x006e
和0x0301
表示。const str1 = '\u0144'; //ń const str2 = '\u006e\u0301'; //ń console.log({ str1, str2, });//{ str1: 'ń', str2: 'ń' }
这两种表示方式,是视觉和语义上都是相同的,它们是标准等价的。但是,在代码层面它们却是不同的,
str1
是一个码点,str2
是两个码点,这很有可能会导致问题。console.log(str1.length, str2.length);//1 2 console.log(str1 === str2);//false
normalize
函数便是为了解决这种问题,两个字符串通过normalize
函数实现正规化之后,就不会再出现这种问题了。let str1 = '\u0144'; //ń let str2 = '\u006e\u0301'; //ń //正规化 str1 = str1.normalize(); str2 = str2.normalize(); console.log({ str1, str2, }); //{ str1: 'ń', str2: 'ń' } console.log(str1.length, str2.length); //1 1 console.log(str1 === str2); //true
新增的unicode表示方法
在之前,我们表示unicode字符可以通过
\u+码点
的方式,ES6新增了一种表示方式,即\u+{ 码点 }
。这两种方式的不同之处,也很容易想到,
\u+{ 码点 }
支持写入辅助平面的4字节码点,而\u+码点
仅支持基本平面的2字节码点。//对于基本平面的2字节码点,两种没有区别 const str1 = '\u{0144}'; const str2 = '\u0144'; console.log(str1 === str2); //true //高音符号 const str3 = '\u{1d11e}'; //错误的表示方法,被识别为了 \u1d11 和 e 两个字符 const str4 = '\u1d11e'; console.log(str4,str3===str4); //ᴑe false
unicode确实让人头痛,如果有朋友对于unicode不太了解,可以在评论区留言,我会再发一篇详细介绍unicode与JS的文章。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。