es6之模板字符串

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 字符串,防止用户输入恶意内容。
标签模板的另一个应用,就是多语言转换(国际化处理)

你可能感兴趣的:(es6,前端,ecmascript)