(1)字符的 Unicode 表示法
  以往JS支持\uxxxx形式表示一个字符,但只限于\u0000~\uFFFF的字符。超
  过这个范围的,必须用两个双字节形式表示:
    "\u20BB7" //" 7" 超过了显示7
  ES6要将码点放入大括号,就能正确解读该字符:
    "\u{20BB7} // "??"
    "\u{41}\u{42}\u{43}" // "ABC"
  目前,js有六种方法表示一个字符:
    '\z' === 'z' // true
    '\172' === 'z' // true
    '\x7A' === 'z' // true
    '\u007A' === 'z' // true
    '\u{7A}' === 'z' // true
(2)codePointAt()
  js中字符以UTF-16的格式储存,每个字符固定2个字节,对于那些4个字节
  存储的字符(大于0xFFFF的字符),js认为是2个字符:
    var s = "𠮷";
    s.length // 2
    s.charCodeAt(0) // 55362 十进制
    s.charCodeAt(1) // 57271
  ES6提供了codePointAt方法,处理4个字节储存的字符
    var s = '𠮷a';
    s.codePointAt(0) // 134071 从0开始
    s.codePointAt(1) // 57271
    s.codePointAt(2) // 97
  使用for of循环,会正确识别32位的字符
    var s = '𠮷a';
    for (let ch of s) {
      console.log(ch.codePointAt(0).toString(16));
    }
  codePointAt方法是测试一个字符是两个字节还是四个字节最简单方法:
    function is32Bit(c) {
      return c.codePointAt(0) > 0xFFFF;
    }
    is32Bit("𠮷") // true
    is32Bit("a") // false
(3)String.fromCodePoint()
   反编译,将码点返回对应字符;
    ES5中提供String.fromCharCode,但不识别32位的,即大于0xFFFF的
      String.fromCharCode(0x20BB7)
        // "ஷ" 实际上是0x20BB,7被删除
      String.fromCodePoint(0x20BB7)
        // "𠮷"
  如果有多个参数,合并成一个字符串输出
(4)字符串的遍历器接口
  ES6为字符串添加了遍历器接口,使得字符串可以被for...of循环遍历
    for (let codePoint of 'foo') {
      console.log(codePoint)
    }
      // "f"
      // "o"
      // "o"
  另外这个遍历器最大的优点是可以识别大于0xFFFF的码点。
(5)at()
  ES5中提供charAt()方法,返回字符串给定位置的字符,但却不能识别32位的
    'abc'.charAt(0) // "a"
    '𠮷'.charAt(0) // "\uD842"
  ES6新增at()方法,可以识别32位的
    '𠮷'.at(0) // "𠮷"
(6)includes(), startsWith(), endsWith()
  传统中,js只有indexOf()方法,确定一个字符串是否包含在另一个中
  ES6新增加了3个:
    includes():返回布尔值,表示是否找到了参数字符串。
    startsWith():返回布尔值,表示参数字符串是否在源字符串的头部。
    endsWith():返回布尔值,表示参数字符串是否在源字符串的尾部。
      var s = 'Hello world!';
      s.startsWith('Hello') // true
      s.endsWith('!') // true
      s.includes('o') // true
  三个方法都支持第二个参数,表示开始搜索的位置:
      var s = 'Hello world!';
      s.startsWith('world', 6) // true
      s.endsWith('Hello', 5) // true
      s.includes('Hello', 6) // false
  有第二个参数N时,.endsWith针对前N个字符
(7)repeated()
  repeat方法返回一个新字符串,表示将原字符串重复n次:
    'x'.repeat(3) // "xxx"
    'na'.repeat(0) // ""
  参数中负数报错,0到-1之间的小数,NaN都等同0;
  参数中字符串可以转为数字的,按数字处理,转不成的额按0处理:
    'na'.repeat('na') // ""
    'na'.repeat('3') // "nanana"
(8)padStart(),padEnd()
  ES6新增字符串补全长度,某个字符串长度不够,可以在头部或尾部补全;
    'x'.padStart(5, 'ab') // 'ababx'
    'x'.padStart(4, 'ab') // 'abax'
    'x'.padEnd(5, 'ab') // 'xabab'
    'x'.padEnd(4, 'ab') // 'xaba'
  padStart(),从头部补全,padEnd(),尾部补全
    第一个参数表示补为多长,第二个表示用于不全的字符串,第二个参数没有
    的时候,默认为空格补全;
  如果原字符串的长度,等于或大于指定的最小长度,则返回原字符串
    'xxx'.padEnd(2, 'ab') // 'xxx'
  如果原字符串和补全字符串超过指定长度,会删除超过位数的补全字符串
    'abc'.padStart(10, '0123456789') // '0123456abc'
  常见用途:为数值补全指定位数、生成提示字符串格式
    '12'.padStart(10, '0') // "0000000012"
    '09-12'.padStart(10, 'YYYY-MM-DD') // "YYYY-09-12"
(9)模版字符串(重头戏)
  模版字符串用反引号 ` 表示,可以当作普通字符串,也可以加入变量
    var name = "Bob", time = "today";
    `Hello ${name}, how are you ${time}?`
  变量写在${}中,可以任何运算、对象、函数,但须声明过;
  模版中需要使用反引号用反斜杠 \ 转义
    var greeting = `\`Yo\` World!`;
  使用模版表达多行字符串时,所有的空格和缩进都会被保留在输出之中:
    const a = `<ul>
            <li>first</li>
            <li>second</li>
          </ul>`;
  可以用trim()方法删除换行,a.trim();

(10)标签模版
  标签模板其实不是模板,而是函数调用的一种特殊形式。“标签”指的就
  是函数,紧跟在后面的模板字符串就是它的参数:
    alert`123` // 等同于 alert(123)
(11)String.raw()
  ES6还为原生的String对象,提供了一个raw方法;
  往往用来充当模板字符串的处理函数,返回一个斜杠都被转义(即斜杠前面
  再加一个斜杠)的字符串,对应于替换变量后的模板字符串:
    String.raw`Hi\n${2+3}!`; // "Hi\\n5!"
  已经转义的不做任何处理:
    String.raw`Hi\\n` // "Hi\\n"