ES6 加强了对 Unicode 的支持,并扩展可字符串对象。
1)字符串 Unicode 表示法
js 允许采用 \uxxxx 形式表示一个字符,其中 xxxx 表示字符的 Unicode 码点。但是这种表示只限于码点在 \u0000 ~ \uFFFF 之间的字符。超出这个范围的字符,必须使用两个双字节的形式表示。
ES6 对于这一点进行了改进,只要将码点放入大括号,就能正确解读该字符。
"\uD842\uDFB7" === "\u{20BB7}" // true (ES6新增)
'\z' === 'z' // true
'\122' === 'z' // true
'\x7A' === 'z' // true
'\u007A' === 'z' // true
'\u{7A}' === 'z' // true (ES6新增)
2)codePointAt()
JavaScript 会将\u{20BB7}z
视为三个字符,charCodeAt() 方法只能分别返回\u{20BB7}
的前两个字节和后两个字节的值,以及 z
的编码。而codePointAt() 方法在第一个字符上,正确的识别了\u{20BB7}
,并返回了它的十进制码点134071.;第二个字符为\u{20BB7}
的后两个字节;第三个字符为z
的编码。
var s = '\u{20BB7}z';
s.charCodeAt(0); // 55362 \uD842
s.charCodeAt(1); // 57271 \uDFB7
s.charCodeAt(2); // 122 \u7A
-----------------------------------
s.codePointAt(0) // 134071 \u20BB7
s.codePointAt(1) // 57271 \uDFB7
s.codePointAt(2) // 122 \u7A
可以看出 codePointAt() 方法可以正确的返回32位的UTF-16字符的码点。对于那些两个字节存储的常规字符,它的返回值与 chartCodeAt() 方法相同。
codePointAt() 方法可用来测试字符是由两个字节还是四个字节组成。x.codePointAt(0)
是否大于 0xFFFF
。
3)String.fromCodePoint()
ES5 提供String.fromCharCode()
方法用于从码点返回对应字符,但是该方法不能识别32位的UTF-16字符(Unicode编号大于0xFFFF
)。
ES6 提供了String。fromCodePoint()
方法,可以识别大于0xFFFF
的字符。该方法也可以接收多个参数,此时将它们合并成一个字符串返回。
4)字符串的遍历接口
ES6 为字符串添加了遍历接口,是的字符串可以被for...of
循环遍历。
5)at()
ES5 对字符串提供了charAt()
方法,返回字符串给定位的字符,该方法不能识别码点大于0xFFFF
的字符。
目前,有提案提出了at()
方法,用于识别码点大于0xFFFF
的字符。
6)normalize()
ES6 提供字符串实例的normalize()
方法,用来将字符的不同表示方法统一为同样的形式,这称为Unicode正规化。
7)includes(),startWith(),endWith()
includes() 返回布尔值,表示是否找到了参数字符串。如有第二个参数,表示查找范围是从第 n 个位置到字符串结束。
startWith() 返回布尔值,表示参数字符串是否在源字符串的头部。如有第二个参数,表示查找范围是从第 n 个位置到字符串结束。
endtWith() 返回布尔值,表示参数字符串是否在源字符串的尾部。如有第二个参数,表示查找范围是从 0 到第 n 个位置字符串。
8)repeat()
repeat() 方法返回一个新字符串,表示将源字符串重复 n 次。参数若是小数,则取整数部分;若是负数(小于-1)或Infinity
,会报错。(-1,0)区间等同于 0(先取整变为-0);参数NaN
等同于0。如果是字符串,则先转换成数字。
9)padStart(),padEnd()
ES2017 引入了字符串补全长度的功能。如果某个字符串长度不够指定长度,会在头部或尾部补全。padStart() 用于头部补全, padEnd() 用于尾部补全。它们都接受两个参数,第一个参数用来指定字符串的最小长度,第二个参数是用来补全的字符串。
如果远字符串的长度,等于或大于指定的最小长度,则返回字符串本身。
如果用来补全的字符串和原字符串的长度和超出了指定的最小长度,则会截去超出位数的补全字符串。
如果省略第二个参数,默认使用空格补全长度。
10)模板字符串
ES6 引入了模板字符串(template string)。模板字符串是增强的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。
如果使用模板字符串表示多行字符串,所有空格和缩进都会被保留在输出之中。
如果在模板字符串中需要使用反引号,则在前面使用反斜杠转义。
模板字符串中可以使用${}
来嵌套JavaScript变量、表达式、函数调用。如果${}
大括号中的变量没有声明,将报错。
注意:模板字符串默认会将字符串转义,导致无法嵌入其他语言。如模板字符串会将\uxxxx
当做 Unicode 字符进行转义,所以\unicode
解析时报错。
let bad = `bad escape sequence: \unicode`; // 报错
11)标签模板
模板字符串可以紧跟在函数名后,该函数将被调用,模板字符串将被处理为函数的参数。
alert`123` => alert(123)
---------------------------------------
function tag(stringArr, ...values){ }
var a = 5, b = 6;
tag`Hello &{a + b} world &{a + b}`;
=> tag(['Hello ', ' world', ''], 15, 50);
tag()
函数的第一个参数是一个数组,该数组的成员是模板字符串中那些没有变量替换的部分,也就是说,变量替换只发生在数组的第一个成员和第二个成员之间,第二个与第三个成员之间,以此类推。
tag()
函数的其他参数,都是模板字符串各个变量被替换后的值。
标签模板用途:
1)可以防止用户输入恶意代码内容。
function SaferHTML(templateData) {
var s = templateData[0];
for (var i = 1; i < arguments.length; i++) {
var arg = String(arguments[i]);
// Escape special characters in the substitution.
s += arg.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">");
// Don't escape special characters in the template.
s += templateData[i];
}
return s;
}
var sender = '<script>alert("abc")</script>'; // 恶意代码
var message = SaferHTML`<p>${sender} message.</p>`;
message =>
<p><script>alert("abc")</script> message.</p>
2)国际化处理。
3)在JavaScript中嵌套其他语言。
12、String.raw()
String.raw()
方法,往往用来充当模板字符串的处理函数,它将所有变量替换,而且对斜杠进行转义(若已经转义,则不操作)。
String.raw`Hi\n${2+3}!`; // "Hi\\n5!"
String.raw`Hi\\n`; // "Hi\\n"
String.raw()
方法也可以作为正常的函数使用。这时,它的第一个函数,应该是一个具有raw
属性的对象,且raw
属性的值应该是一个数组。
String.raw({ raw: 'test' }, 0, 1, 2); // 't0e1s2t'
// 等同于
String.raw({ raw: ['t','e','s','t'] }, 0, 1, 2);