ECMA Script 6_字符串_扩展_字符 是4字节还是2字节?_模板字符串

ES6 字符串扩展

ES6 加强了对 Unicode 的支持,并且扩展了字符串对象

  • 字符 的 Unicode 表示法

允许采用 \uxxxx 形式表示一个字符

其中 xxxx 表示字符的 Unicode 码点

 

  • 这种表示法只限于码点在 \u0000 ~ \uFFFF 之间的字符。
  • "\u0061"    // "a"
  • 超出这个范围的字符,必须用两个双字节的形式表示
  • "\uD842\uDFB7"    // "𠮷"
  • \u 后面的码点 超过0xFFFF的数值(比如\u20BB7),JavaScript 会理解成\u20BB+7
  • 由于 \u20BB 是一个不可打印字符,所以只会显示一个空格,后面跟着一个 7
  • "\u20BB7"    // " 7"
  • ES6 对这一点做出了改进,只要将码点放入大括号,就能正确解读该字符,而无须双字节
  • "\u{20BB7}" // "𠮷"
  • "\u{41}\u{42}\u{43}" // "ABC"
  • let hello = 123;
  • hell\u{6F} // 123
  • console.log('\u{1F680}' === '\uD83D\uDE80'); // true
  • 所以,在 ES6 中,共有 6 中方式表示一个字符
  • console.log('\z' === 'z');    // true
    console.log('\172' === 'z');    // true
    console.log('\x7A' === 'z');    // true
    console.log('\u007A' === 'z');    // true
    console.log('\u{7A}' === 'z');    // true
  • ES6 提供了 codePointAt 方法,能够正确处理 4 个字节储存的字符,返回一个字符的码点
  • let s = '𠮷a';
    
    s.codePointAt(0);    // 134071
    s.codePointAt(1);    // 57271
    
    s.codePointAt(2);    // 97

总之,codePointAt 方法会正确返回 32 位的 UTF-16 字符的码点

对于那些两个字节储存的常规字符,它的返回结果与 charCodeAt 方法相同

  • codePointAt 方法返回的是码点的十进制值,如果想要十六进制的值,可以使用 toString 方法转换一下
  • let s = '𠮷a';
    
    s.codePointAt(0).toString(16);    // "20bb7"
    s.codePointAt(2).toString(16);    // "61"
  • 测试一个字符由两个字节还是由四个字节组成的
  • function is32Bit(c) {
        return c.codePointAt(0) > 0xFFFF;
    }
    
    is32Bit("𠮷");    // true
    is32Bit("a");    // false
  • ES6 提供了 String.fromCodePoint() 方法,可以识别大于 0xFFFF 的字符,弥补了 String.fromCharCode 方法的不足
  • String.fromCodePoint(0x20BB7);    // "𠮷"
    console.log(String.fromCodePoint(0x78, 0x1f680, 0x79) === 'x\uD83D\uDE80y');    // true
  • ES6 对数组扩展了 对字符串包含问题的 API
  • let str = 'Hello world!';
    
    str.startsWith('Hello');    // true 是否以 'Hello' 开头
    str.endsWith('!');    // true 是否以 '!' 结尾
    str.includes('o');    // true 是否包含 'o'

支持 两个参数

  • let str = 'Hello World!';
    
    str.startsWith('world', 6);    // true 从第 n 个开始,之后字符串 是否以 world' 开头
    str.endsWith('Hello', 5);    // true 从第 n 个开始,之前的字符串 是否以 'Hello' 结尾
    str.includes('Hello', 6);    // false 从第 n 个开始,之后的字符串 是否包含 'Hello'
  • str.repeat(2);    // ES6 扩展 API,将 str 重复 2 次返回新字符串,而不影响 原字符串 str

如果传入参数为小数,则向下取整

  • 'na'.repeat(2.9);    // "nana"    等同于 'na'.repeat(2)
    
    // 负数, 或者 infinity 会报错
    'na'.repeat(Infinity);    // RangeError
    'na'.repeat(-1);    // RangeError

如果是字符串,则转换为 Number 类型

  • 'na'.repeat('na');    // ""
    'na'.repeat('3');    // "nanana"
    
    'na'.repeat(NaN);    // "" 相当于 0
    'na'.repeat(-0.9);    // "" -1 到 0 之间,相当于 0
  • ES6 引入字符串补全长度的功能,从头补全 str.padStart(),或者从尾补全 str.padEnd()

第一个参数 指定最大字符串长度,第二个参数用于补全的字符串

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

如果 最大长度 大于 原字符串,则补全不生效,返回原字符串

  • 'abc'.padStart(2, 'ab');    // 'abc'
    'ccc'.padEnd(2, 'ab');    // 'ccc'

如果省略第二个用于补全的字符串,则 默认以空格补全

  • 'a'.padStart(4);    // '   a'
    'b'.padEnd(4);    // 'b   '
  • 应用:
  • 为数值补全指定位数。下面代码生成 10 位的数值字符串
  • '1'.padStart(10, '0');    // "0000000001"
    '12'.padStart(10, '0');    // "0000000012"
    '123456'.padStart(10, '0');    // "0000123456"
  • 生成 字符串格式。
  • '12'.padStart(10, 'YYYY-MM-DD');    // "YYYY-MM-12"
    '09-12'.padStart(10, 'YYYY-MM-DD');    // "YYYY-09-12"
  • ES6 引入了模板字符串

模板字符串(template string)是增强版的字符串,用反引号(`)标识。

它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量

模板字符串的大括号内部,就是执行 JavaScript 代码,因此如果大括号内部是一个字符串,将会原样输出

  • // 普通字符串
    `In JavaScript '\n' is a line-feed.`
    
    // 多行字符串
    `In JavaScript this is
     not legal.`
    
    console.log(`string text line 1
    string text line 2`);
    
    // 字符串中嵌入变量
    let name = "Bob", time = "today";
    `Hello ${name}, how are you ${time}?`    // 变量必须写在 `${}` 里面

如果在模板字符串中需要使用反引号,则前面要用反斜杠转义

  • let greeting = `\`Yo\` World!`;

模板字符串表示多行字符串,所有的空格和缩进都会被保留在输出之中

  • $('#list').html(`
    <ul>
        <li>first</li>
        <li>second</li>
    </ul>
    `);

花括号内 可以放入表达式,进行计算

  • let x = 1;
    let y = 2;
    
    console.log(`${x} + ${y} = ${x + y}`);     // "1 + 2 = 3"
    
    console.log(`${x} + ${y * 2} = ${x + y * 2}`);    // "1 + 4 = 5"
    
    let obj = {x: 1, y: 2};
    console.log(`${obj.x + obj.y}`);    // "3"

模板字符串之中还能调用函数

  • function fn() {
        return "Hello World";
    }
    
    console.log(`foo ${fn()} bar`);    // foo Hello World bar
  • 标签模板: 特别的函数调用方式
  •     let a = 5;
        let b = 10;
    
        function tag(s, v1, v2) {
            console.log(s[0]);
            console.log(s[1]);
            console.log(s[2]);
            console.log(s[3]);
            console.log(v1);
            console.log(v2);
    
            return "OK";
        }
    
        console.log(tag`Hello ${ a + b } world ${ a * b}RyenToretto`);
        // "Hello "
        // " world "
        // RyenToretto"
        // ""
    
        // 15
        // 50
    
        // "OK"

应用:

  • 就是过滤 HTML 字符串,防止用户输入恶意内容
  • let message = SaferHTML`<p>${sender} has sent you a message.</p>`;
    
    function SaferHTML(templateData) {
        let s = templateData[0];
        
        for (let i = 1; i < arguments.length; i++) {
            let arg = String(arguments[i]);
            
            // Escape special characters in the substitution.
            s += arg.replace(/&/g, "&amp;")
                    .replace(/</g, "&lt;")
                    .replace(/>/g, "&gt;");
            
            // Don't escape special characters in the template.
            s += templateData[i];
        };
        
        return s;
    };

ES6 还为原生的 String 对象,提供了一个 raw 方法——模板字符串的处理函数

将所有变量替换,而且对斜杠进行转义,方便下一步作为字符串来使用

  • 返回一个斜杠都被转义(即斜杠前面再加一个斜杠)的字符串
  • String.raw`Hi\n${2+3}!`;    // 返回 "Hi\\n5!"
    
    String.raw`Hi\u000A!`;    // 返回 "Hi\\u000A!"

即使 原字符串的斜杠已经转义,String.raw() 还是会进行再次转义

 

posted @ 2018-12-14 22:49  耶梦加德  阅读(234)  评论(0编辑  收藏  举报