1.字符的Unicode表示法
es6加强了对Unicode的支持,允许用\uxxxx的形式来表示一个字符,其中xxxx是该字符的Unicode码点。
但是这种用法用一个限制就是只限于Unicode码点在\u0000~\uFFFF之间的字符
如果超出这个范围,则必须用两个双字节的形式表示。
console.log("\u20AA7") //₪7
console.log("\u20AA"+7) //₪7
console.log("\uD842\uDEA7") //""
当我们使用"\u20AA7"表示字符时,由于其超出了\u0000~\uFFFF这个范围,所以js会将其当成"\u20AA"+7
所以我们打印出来后,是₪7,其中₪就是"\u20AA"对应的字符,
这个时候我们可以用两个双字节的形式来表示之后就能正确的得到""这个字符。
那么问题来了,为什么"\u20AA7"的两个双字节形式会是"\uD842\uDEA7"呢?
其转换过程其实是这样的
第一步、对于大于0xFFFF的字符,先减去0x10000得出10AA7
第二步、将10AA7转换成2进制:0001 0000 1010 1010 0111
第三步、分解成两个码点:
1. 1101 10|0001 0000 10 ==>D842
2. 1101 11|10 1010 0111 ==>DEA7
在转变的时候前面6位是填充到两个码点里面去的。
每一次转变都固定不变
上述的转换方式无疑是非常繁琐的,所以es6对于这点做出来改进,
现在只需要我们将码点放入大括号中,就能够正确解读该字符
console.log("\u{20AA7}") //""
所以现在我们对于一个字符可以使用六种表示方式
console.log('a') //a
console.log('\a') //a
console.log('\141') //a
console.log('\x61') //a
console.log('\u0061') //a
console.log('\u{61}') //a
2.字符串的遍历器接口
es6为字符串新增了遍历器的接口,使的字符串可被for...of循环遍历
而且使用for...of循环遍历时最大的优点是可以识别大于0xffff的码点
for (let a of 'foo') {
console.log(a) //f 0 0
}
3.关于直接输入U+2028和U+2029的问题
由于js规定有5个字符是不能再字符串中直接使用的,只能使用转义形式
分别是U+005C(反斜杠)、U+000D(回车)、U+2028(行分隔符)、U+2029(段分隔符)、U+000A(换行符)
但是在JSON格式中允许字符串中直接使用 U+2028(行分隔符)和 U+2029(段分隔符)。
所以如果我们在执行JSON.parse时,如果JSON中有U+2028(行分隔符)和 U+2029(段分隔符),则可能会报错。
于是为了消除这个问题,es2019允许了js字符串直接输入 U+2028(行分隔符)和 U+2029(段分隔符)。
4.JSON.stringify()的改造
根据标准,JSON数据必须是UTF-8编码,而UTF-8规定,0xD800-0xDFFF之间的码点不能单独使用,必须配对
而当我们执行JSON.stringify()方法时,有可能会返回一个单独的0xD800-0xDFFF之间的码点。
为了确保合法性,es2019改变了JSON.stringify()的行为,
当遇到0xD800-0xDFFF之间的单独码点或者是无法配对的码点时,
会返回转义字符串,留给应用自行处理。
let a = JSON.stringify('\u{D834}')
let b = JSON.stringify('\uDF06\uD834')
console.log(a) //"\ud834"
console.log(b) //"\udf06\ud834"
5.模板字符串
传统的 JavaScript 语言,输出模板通常是这样写的
let a = 1;
let b = 2;
let str='要么是' + a + '要么是' + b + '';
console.log(str); //要么是1要么是2
document.getElementById('hahaha').innerHTML = str
es6引入模板字符串
let a = 1;
let b = 2;
let str=`要么是${a}要么是${b}`;
console.log(str); //要么是1要么是2
document.getElementById('hahaha').innerHTML = str
模板字符串的优点:
可以当做普通字符串使用
可以定义多行字符串
可以在字符串中嵌入变量
let a = 1;
let b = 2;
let str=`要么是${a}
要么是${b}`;
console.log(str);
//要么是1
// 要么是2
如果模板字符串中需要使用(`)符号时,需使用\进行转义
所有的模板字符串中的空格与换行都是会被保留的
如果不想要这个换行的话可以使用trim方法消除掉
//前面有换行
$('#list').html(`
- first
- second
`);
//前面无换行
$('#list').html(`
- first
- second
`.trim());
模板字符串${}中可以放入任意js表达式、进行运算、引入对象属性以及调用函数
let a = 1;
let b = 2;
let obj={
name:'jxy',
id:'666'
};
let fn= function(){
console.log('函数调用了') //函数调用了
return 'fn函数'
}
let str =`表达式:${a}+${b}=${a+b},对象引用:${obj.name}${obj.id},函数调用${fn()}`
console.log(str) //表达式:1+2=3,对象引用:jxy666,函数调用fn函数
模板字符串嵌套
const objlist=[
{
name:'jxy',
id:'666'
},
{
name:'江小余',
id:'888'
}
]
let jxyFn=(objlist)=>`${objlist.map((item)=>`我是${item.name},代号:${item.id}`)}`
console.log( jxyFn(objlist));
6.模板编译
编译就是一种格式转换成另一种格式的过程,模板字符串之所以与常规字符串有所不同,这些都是模板编译的结果。
下列是一个常规的字符串模板,该模板使用的是<%...%>来放置js代码的,使用<%=...%>来输出js表达式结果的。
let template = `
<% for(let i=0; i < data.supplies.length; i++) { %>
- <%= data.supplies[i] %>
<% } %>
`;
使用模板编译函数来实现上面的字符串模板编译
//构建模板生成函数
function compile(template) {
const evalExpr = /<%=(.+?)%>/g;
const expr = /<%([\s\S]+?)%>/g;
//正则替换
template = template
.replace(evalExpr, '`);jxy( $1 );jxy(`')
.replace(expr, '`);$1jxy(`');
template = 'echo(`' + template + '`);';
console.log(template)
// echo(``);
// for(let i=0; i < data.supplies.length; i++) {
// echo(`- `);
// echo( data.supplies[i] );
// echo(`
`);
// }
// echo(`
`);
let script =`(function parse(data){
let output = "";
function echo(html){
output += html;
}
${ template }
return output;
})`;
return script;
}
let parse = eval(compile(template));
document.getElementById('hahaha').innerHTML = parse({ supplies: [ "broom", "mop", "cleaner" ] });
7.标签模板
一种特殊形式的函数调用方式,“标签”指的是函数,而模板字符串则是函数的参数。
如果模板字符串中有变量时,会将模板字符串处理成多个参数再进行函数调用
let a = 5;
let b = 10;
function jxy(a,b,c,d) {
console.log(a); //(3) ['Hello ', ' world ', '', raw: Array(3)]
console.log(b); //15
console.log(c); //50
console.log(d); //undefined
}
jxy `Hello ${ a + b } world ${ a * b }`;
tag函数的第一个参数是一个数组,该数组的成员是模板字符串中那些没有变量替换的部分,
tag函数的其他参数,都是模板字符串各个变量被替换后的值。
tag`Hello ${ a + b } world ${ a * b }`;
// 等同于
tag(['Hello ', ' world ', ''], 15, 50);
“标签模板”的一个重要应用,就是过滤 HTML 字符串,防止用户输入恶意内容。
标签模板的另一个应用,就是多语言转换(国际化处理)