你不知道的JavaScript字符

417 阅读3分钟

这是我参与8月更文挑战的第15天,活动详情查看:8月更文挑战

本来觉得没什么,又看红宝书看到很多关于Unicode的东西,对这个知识点还是比较生疏,所以总结出来的JavaScript字符笔记~

JavaScript字符

1. length

这个应该是最经常用的方法了吧;JavaScript字符串由16位码元组成,每16位码元对应一个字符;也就是说,字符串的length属性表示字符串包含多少16位码元。

let nickname = "mannqo";
console.log(nickname.length);  // 6

2. charAt()

charAt()方法返回给定索引位置的字符,由传给方法的整数参数指定;

let nickname = "mannqo";
console.log(nickname.charAt(2));  // "n"

3. charCodeAt()

JavaScript字符串使用了两种Unicode编码混合的策略:UCS-2UTF-16。对于可以采用16位编码的字符(U+0000 ~ U+FFFF);每一个字母或文字都有其对应的Unicode编码;charCodeAt()方法就可以查看指定码元的字符编码;

let message = "abcde";
// c的对应的编码:U+0063
console.log(mes.charCodeAt(2));  // 99 (十进制99等于十六进制63

4. fromCharCode()codePointAt()

fromCharCode()方法用于根据给定的UTF-16码元创建字符串的字符。这个方法可以接受任意多个数值,并返回将所有数值对应的字符拼接起来的字符串;

console.log(String.fromCharCode(0x61, 0x62, 0x63, 0x64));  // abcd

对于U+0000 ~ U+FFFF范围类的字符,上面几个方法返回的结果和预期是一样的;这是因为在这个范围类,每个字符都是用16位表示的,而这几个方法也都基于16位码元完成操作。只要字符编码大小与码元大小一样,就能正常工作;而16位只能唯一标识65536个字符;

为了标识更多的字符,Unicode采用了一个策略,即每个字符使用另外16位取选择一个增补平面。也就是使用2个16位码元的策略称为代理对。例如表情符号的编码:

let message = "ab😊cd";
console.log(message.length);  // 6

但是上面这几个方法仍然是把16码元当作一个字符

console.log(message.charAt(2));   // <?>
console.log(message.charAt(3));   // <?>
console.log(message.charCodeAt(2));   // 55357
console.log(message.charCodeAt(3));   // 56842

log.png 但是事实上,索引2和索引3对应的码元应该被看成一个代理对,只对应一个字符,fromCharCode()方法仍然返回正确的结果,是因为它实际上是基于提供的二进制表示直接组合成字符串。浏览器可以正确解析由两个码元构成的代理对,并正确地将其识别为一个Unicode笑脸字符。

为了正确解析既包含单码元字符又包含代理对字符的字符串,可以用codePointAt()代替charCodeAt()codePointAt()可以从指定码元位置识别完整的码点。

console.log(message.codePointAt(2));  // 128522
console.log(message.codePointAt(3));  // 56842

注意:如果传入的码元索引并非代理对的开头,就会返回错误的码点,比如上面这个索引3,并非是笑脸字符的代理对开头,因此返回的就是错误的码点;

charCodeAt()有对应的codePointAt()fromCharCode()也有一个对应的fromCodePoint(),这个方法可以接收任意数量的码点,返回对应字符拼接起来的字符串;

console.log(String.fromCharCode(97, 98, 55357, 56842, 100, 101));//ab😊cd
console.log(String.fromCodePoint(97, 98, 128522, 100, 101));  //ab😊cd