字符处理



ES6 可以自动识别4字节的码点。但是,为了保持兼容,length属性还是原来的行为方式。为了得到字符串的正确长度,可以先转为数组Array.from(string).length
遍历字符串:for(let s of str) {} // [...""]
"\ud83d\udca9"
D800-DBFF: High-half zone of UTF-16
DC00-DFFF: Low-half zone of UTF-16

模板字符串标签tag函数(可以不用括号直接对模板字符串使用):String.raw `Hi\n!`; // "Hi\\n!", 用来获取一个模板字符串的原始字面量值(转义符号会被转义成原始字面量【console显示】,但还是可以运行内插表达式)的,内置唯一tag函数。
// 普通函数基本不需要使用: String.raw({raw: "test"}, 0, 1, 2); // => "t0e1s2t"

js转义字符串: '\x21', '\u0333', '\u{2F804}','\xA9' === '\251' // Latin-1 encoding specified ,16/8 进制表示编码
// 其他任何不属于转义的字符都会直接输出原字符并且忽略转义符
// js数字 0o11 八进制。0b11 二进制。0x11 16进制。


js 普通 unicode 表示法对 4 字节的码点无效。ES6修正了这个问题,只要将码点放在大括号内,就能正确识别 // '\u{1F4A9}'

HTML表单元素的 maxLength 属性不能识别4字节码点,maxLength 也不能限制 js 设置的文本长度。但是能限制中文输入法的输入(keypress不能限制)。

ES6提供了u修饰符,对正则表达式添加4字节码点的支持。

Unicode 提供了两种表示方法。一种是带附加符号的单个字符,即一个码点表示一个字符,比如 Ǒ 的码点是U+01D1;另一种是将附加符号单独作为一个码点,与主体字符复合显示,即两个码点表示一个字符,比如Ǒ可以写成O(U+004F) + ˇ(U+030C)。

这两种表示方法,视觉和语义都完全一样,理应作为等同情况处理。但是,JavaScript 无法辨别。

ES6 提供了 normalize 方法,允许"Unicode正规化",即将两种方法转为同样的序列。


// NFD:Canonical Decomposition,用两个码点表示


css js 不会处理 \r,\r\n 和 \n 一样换行。

HTML显示特殊字符可以通过使用HTML实体、十进制字符引用和十六进制字符/Unicode引用(只有4位数,不要和CSS颜色混为一谈)。如表示∾̳可以这样写:
∾̳
̳
̳
🏁 // emoji
如果只知道 ASCII 码,那么可以将其转换到 Unicode 在显示如:

html中的换行被解释成text节点。换行和多个空格只渲染成一个空格,但是元素的text节点都记得很清楚(换行,空格数)
⁠ 不换行零宽空格

css样式中的content可以使用Unicode编码∾̳:
\223E\0333
\A 换行(000A Unicode编码),换行要像其它元素一样white-space: pre;
不需要在"\"后面添加u,而js需要。

在css和js中\为转义字符,HTML中&为转义字符
js使用Unicode字符集编写的,因为有些程序不支持,所以可以用转义符编写。\u0333


Unicode 编码方式:
目前实际应用的統一碼版本对应于UCS-2,使用16的编码空间,占2字节
基本多文种平面的字符的编码为U+hhhh,其中每个h代表一个十六进制数字,与UCS-2编码完全相同。而其对应的4字节UCS-4编码后两个字节一致,前两个字节則所有位均为0。
Unicode实现方式称为Unicode转换格式(Unicode Transformation Format,简称为UTF):如果一个仅包含基本7位ASCII字符的Unicode文件可以使用UTF-8编码,这是一种变长编码,它将基本7位ASCII字符仍用7位编码表示,占用一个字节(首位补0)。
带有附加符号拉丁文希腊文西里尔字母亚美尼亚语希伯来文阿拉伯文叙利亚文它拿字母则需要两个字节编码(Unicode范围由U+0080至U+07FF)。其他基本多文种平面(BMP)中的字符(这包含了大部分常用字,如大部分的汉字)使用三个字节编码(Unicode范围由U+0800至U+FFFF因为存在一字节表示的字符,所以比unicode的表示还要多一个字节)。

BOM 用于标记一个文本文件使用 Unicode 编码,其本身是一个Unicode字符(零宽空格 U+FEFF),位于文本文件头部。合并文件等情况下要去掉 BOM

js字符和编码转换:
String.fromCharCode(大于65536/2^16/16^4只返回第一个低位编码,应使用fromCodePoint),String.charCodeAt()。代码为10进制。直接量用'\u{2F804}'表示
encodeURI / encodeURIComponent URL 默认用UTF-8编码
// encodeURI() 不会对本身属于URI的特殊字符进行编码, 用于完整 URI 编码

注意,charCodeAt 总是返回一个小于 65,536 的值。这是因为高位编码单元(higher code point)使用一对(低位编码(lower valued))代理伪字符("surrogate" pseudo-characters)来表示,从而构成一个真正的字符。
return ((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;再用fromCodePoint

btoa,将占一个字节的字符(代码点 65535 以下,Uint8Array 的一个元素)串转为仅含 ASCII 字符的 base64,以便安全传输;
// Uint8Array —> base64 即是先按代码点用 BinaryString 表示 Uint8Array,在 btoa 即可
atob 相反。
function utf8_to_b64( str ) {
return window.btoa(unescape(encodeURIComponent( str )));
}
function b64_to_utf8( str ) {
return decodeURIComponent(escape(window.atob( str )));
}
// Usage:
utf8_to_b64('? à la mode'); // "4pyTIMOgIGxhIG1vZGU="
b64_to_utf8('4pyTIMOgIGxhIG1vZGU='); // "? à la mode"
// 译者注:在js引擎内部,encodeURIComponent(str) 相当于 escape(unicodeToUTF8(str))
// escape 生成新的由十六进制转移序列替换的字符串,以弃用,encodeURI 保留一些字符
// 所以可以推导出unicodeToUTF8(str)等同于unescape(encodeURIComponent(str))
// 每个 Base64 数字代表 6 位数据。 因此,3 个 8 位字节可以由 4 个 6 位Base64数字表示

一个 emoji 可能是多个字符合并的: