ES6-14【Unicode表示法、字符串方法、模板字符串】

一、字符串拓展

(1)字符表示

  1. UTF-16编码回顾

    在JS里面的字符是以utf-16编码方式进行解析

    utf-16的编码范围:

    1. U+0000 ~ U+D800:两个字节表示一个字符
    2. U+D800 ~ U+FFFF:属于空位,四个字节表示一个字符(超出编码极限的字符会以这种方式解析)

    超出编码极限的字符也可用花括号包裹,JS会帮忙解析,例如:\u{2pbb7} == 𠮷

  2. 字符的表示方式

    1. 代码补全

      如果码点不足4位,则用0补全

      console.log('\u0041\u0042\u0043'); // ABC
      
    2. {}解析

      可以解析超出编码极限,或者没有补全的码点

      console.log('\u{0041}\u{0042}\u{0043}'); // ABC
      console.log('\u{41}\u{42}\u{43}'); // ABC
      console.log('\u{2pbb7}'); // 𠮷
      console.log('\uD842\uDFB7' === '\u{20BB7}'); //true
      

(2)码点相关方法

  1. length

    码点长度就是字符长度

    var s = "\u{20BB7}"; // == \uD842\uDFB7
    console.log(s.length); // 2
    

    这样的处理方式不符合预期,只对应了一个字符,长度应该是1,而不是2

  2. charAt(es5)

    输出索引所对应的字符

    缺点:不能正确处理超出编码极限的字符

    console.log(s.charAt(0)); // �
    console.log(s.charAt(1)); // �
    
  3. charCodeAt (es5)

    输出索引所对应的码点(10进制)

    缺点:不能正确处理超出编码极限的字符

    console.log(s.charCodeAt(0)); // 55362
    console.log(s.charCodeAt(0)); // 57271
    // 转成16进制
    console.log(Number.prototype.toString.call(55362,16)); // D842
    console.log(Number.prototype.toString.call(57271,16)); // DFB7
    
  4. codePointAt(es6)

    输出索引所对应的码点(10进制)

    能正确处理超出编码极限的字符,并能拿到索引对应的码点

    var s=  "𠮷a"
    console.log(s.codePointAt(0)); // 134071
    console.log(Number.prototype.toString.call(55362,16)); // 20bb7
    
    console.log(s.length); // 3  长度还是3,只是识别被正确的解析了
    console.log(s.codePointAt(0));//134071 超出编码极限 => 正确解析
    console.log(s.codePointAt(1));//57271 
    console.log(s.codePointAt(2));//97
    console.log(Number.prototype.toString.call(97,16));//61 
    console.log('\u0061'); //a
    console.log('\u{61}'); //a
    

    应用:判断一个字符是2个字节还是4个字节组成

    function is32Bit(c){ // 1Byte == 8Bit
        return c.codePointAt(0) > 0xffff; // 转16进制为10进制
    }
    console.log(is32Bit('吉')); //true
    console.log(0xffff); //655535 比对的时候直接转为10进制比较
    
  5. 迭代器

    可以正确的输出超出编码极限的字符

    var s =  "𠮷a";
    // 对比一下
    for (let i = 0; i < str.length; i++) {
    	console.log(str[i]); // � � a
    }
    
    for (let value of s) {
    	console.log(value); // 𠮷 a   
    }
    
  6. fromCharCode(es5)

    传入一个码点返回一个对应的字符

    缺点:不能识别超出编码极限的码点

    console.log(String.fromCharCode(0x20bb7)); // ஷ
    // 处理方式:当超出物理极限的时候舍弃最高位,返回相应的字符
    console.log(String.fromCharCode(0x20bb7) === String.fromCharCode(0x0bb7)); //true
    
  7. fromCodePoint(es6)

    传入一个码点返回一个对应的字符

    能识别超出编码极限的码点

    String.fromCodePoint(0x20BB7); //吉
    

(3)字符串新增方法

  1. includes / startsWith / endsWith

    判读一个字符串是否在另一个字符串当中、开头、结尾

    let s = "Hello world!";
    console.log(s.includes("o")); // true
    console.log(s.startsWith('Hello')); // true
    console.log(s.endsWith('!')); // true
    
  2. repeat

    把原本的字符串重复N次

    console.log('x'.repeat(3)); //xxx
    console.log('x'.repeat(2.9)); //xx
    console.log('x'.repeat(NaN)); // 空
    console.log('x'.repeat(0)); // 空
    console.log('x'.repeat("3")); //xxx 会有隐式转换
    
  3. padStart / padEnd

    开头、结尾填充 指定字符串 至 指定长度

    console.log('x'.padStart(5,"ab")); //ababx
    console.log('x'.padStart(4,"ab")); //abax
    console.log('x'.padEnd(4,"ab")); //xaba
    console.log('x'.padEnd(5,"ab")); //xabab
    

二、模板字符串

(1)基本用法

let name = 'web'
let info = 'developer'
let m = `I am a ${name} ${info}`;
console.log(m); //I am a web developer

(2)进阶用法

模板里面是表达式,可以做很多事情:

  1. 可以运算

    let x = 1;
    let y = 2;
    console.log(`${x} + ${y} = ${x+y}`) // 1 + 2 = 3
    
  2. 可以调用对象

    let obj = {x:1,y:2};
    console.log(`${obj.x + obj.y}`) // 3
    
  3. 可以调用函数

    function fn(){
        return [1,2,3,4];
    }
    console.log(`foo ${fn()} bar`) //foo 1,2,3 bar
    

    模板里会隐式转换成字符串

  4. 可以嵌套字符串

    let msg = `Hello, ${'place'}`;
    console.log(msg); //Hello, place
    

(3)模板渲染方法

const temp = arr1 => `
    <table>
        ${
            arr1.map(addr => `
                <tr><td>${addr.first}</td></tr>
                <tr><td>${addr.last}</td></tr>
            `)
        }
    </table>
`
const data = [
    {first:"zhang",last:"san"},
    {first:"li",last:"si"},
]
console.log(temp(data));

输出:

在这里插入图片描述

发现有个逗号,这是因为map返回的是一个数组,而模板内部会隐式转换成字符串,所以导致了这个结果

解决方法:

${
    arr1.map(addr => `
        <tr><td>${addr.first}</td></tr>
        <tr><td>${addr.last}</td></tr>
    `).join('')
}

用join方法把数组拼接起来就好了

(4)注入问题

一些恶意的模板数据会通过这种方式渲染到页面

const data = [
    {first:"zhang",last:"<script>alert('abc')</script>"},
    {first:"li",last:"si"},
]  

(5)标签模板

专门用于解决恶意注入的问题

通过标签模板 tag`` 的形式调用函数,可以在函数内部做相应的处理

参数依次是:以{}分隔的字符串,往后{}里的值

let a = 5;
let b = 10;
tag `Hello ${a+b} world${a*b}`;
  function tag($,$1,$2){
      console.log($,$1,$2)
  }
  //['Hello ',' world',''] 13 50

解决方案:

function SaferHTML(tempData) {
    let s = '';
    for (let i = 1; i < arguments.length; i++) {
        let arg = String(arguments[i]);
        s += arg.replace(/</g, "&lt;").replace(/>/g, "&gt;")
    }
    return s;
}
let sender = '<script>alert("abc")<\/script>'
let message = SaferHTML `<p>${sender} has set you message</p>`
console.log(message);

输出:
在这里插入图片描述

注意区分:字符串里的实体符是不会被浏览器解析的,标签里的实体符才会被解析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值