ES5 提供String.fromCharCode方法,用于从码点返回对应字符,但是这个方法不能识别 32 位的 UTF-16 字符(Unicode 编号大于0xFFFF)。
(function (log, S) {
log(S.fromCharCode(0x20BB7)); // ஷ
})(console.log, String)
上面代码中,String.fromCharCode不能识别大于0xFFFF的码点,所以0x20BB7就发生了溢出,最高位2被舍弃了,最后返回码点U+0BB7对应的字符,而不是码点U+20BB7对应的字符。
ES6 提供了String.fromCodePoint方法,可以识别大于0xFFFF的字符,弥补了String.fromCharCode方法的不足。在作用上,正好与codePointAt方法相反。
(function (log, S) {
log(S.fromCodePoint(0x20BB7)); // 𠮷
log(S.fromCodePoint(0x78, 0x1f680, 0x79) === 'x\uD83D\uDE80y'); // true
})(console.log, String)
上面代码中,如果String.fromCodePoint方法有多个参数,则它们会被合并成一个字符串返回。
注意,fromCodePoint方法定义在String对象上,而codePointAt方法定义在字符串的实例对象上。
ES6 还为原生的 String 对象,提供了一个raw方法。
String.raw方法,往往用来充当模板字符串的处理函数,返回一个斜杠都被转义(即斜杠前面再加一个斜杠)的字符串,对应于替换变量后的模板字符串。
(function (log, S) {
log(S.raw`Hi\n${2+3}!`);// 'Hi\\n5!'
log(S.raw`Hi\u000A!`);// 'Hi\\u000A!'
})(console.log, String)
如果原字符串的斜杠已经转义,那么String.raw会进行再次转义。
(function (log, S) {
log(S.raw`Hi\\n`);// 'Hi\\n'
})(console.log, String)
String.raw方法可以作为处理模板字符串的基本方法,它会将所有变量替换,而且对斜杠进行转义,方便下一步作为字符串来使用。
String.raw方法也可以作为正常的函数使用。
这时,它的第一个参数,应该是一个具有raw属性的对象,且raw属性的值应该是一个数组。
(function (log, S) {
log(S.raw({
raw: 'test'
}, 0, 1, 2));
// 't0e1s2t'
// 等同于
log(S.raw({
raw: ['t', 'e', 's', 't']
}, 0, 1, 2));// 't0e1s2t'
})(console.log, String)
作为函数,String.raw的代码实现基本如下。
String.raw = function (strings, ...values) {
let output = '';
let index;
for (index = 0; index < values.length; index++) {
output += strings.raw[index] + values[index];
}
output += strings.raw[index]
return output;
}